Editing Placeholder Text in InInCopy

Users new to InCopy overwhelmingly appreciate having styled placeholder text as part of an assigned (or unassigned) story.

There is one small problem with styled placeholder text that involves how the text is selected for editing. If the user selects a single-line styled paragraph using the traditional triple-click method, the entire line (paragraph) is selected including the ending paragraph marker. This also happens for any paragraph when using the select paragraph keyboard shortcut Shift+Command+P/Shift+Control+P.

If the ending paragraph marker is selected, styling for the paragraph is lost when the user begins typing.

To prevent this from happening you could:

  • Instruct the user to manually select the paragraph by dragging the text cursor over text to edit while being careful to not select the ending paragraph marker. Having Show Hidden Characters enabled from InCopy’s Type menu does make it easier to see where the marker is. But this method requires the user to leave the keyboard to select the text.
  • Have a script installed that selects the paragraph without the ending paragraph marker. Set the script up so it runs using a keyboard shortcut. In fact You might consider overwriting the default shortcut for selecting a paragraph (Shift+Command+P/Shift+Control+P) and use this shortcut for the script.

Using the script, it becomes a simple matter for the user to place the cursor anywhere within the paragraph, enter the keyboard shortcut and begin typing. The downarrow key is pressed to advance to the next paragraph. The keyboard shortcut is keyed in again to select this next paragraph and the user begins typing. And so on.

Some users may find it easier to select the first paragraph using the keyboard shortcut, but then simply press a return after keying in the paragraph. Because paragraph styles are “chained” (using next style properties), the styling for the next paragraph is in place for entering the next paragraph. Instead of replacing the placeholder text, this approach pushes the placeholder text down. At some point during edit this redundant text will need to be deleted. Using the keyboard shortcut Shift+Command+delete can take care of this clean-up chore.

SelectParagraph Script

The script named SelectParagraph can be the key to editing styled placeholder text in InCopy. The script selects the paragraph targeted by the text insertion point without selecting the ending paragraph marker. The steps for this script are as follows:

  • get a reference to the insertion point. (An error is thrown if an insertion point is not selected in a valid paragraph.)
  • get a reference to the paragraph that contains the referenced insertion point
  • set a variable to identify the text range of the paragraph referenced
  • select the text range variable

This would seem to be fairly straightforward. The trick, however, is to get the syntax right for defining the text range. This involves object references.

AppleScript

Object references are a major factor when it comes to writing scripts, yet this concept is one that seems to be hard to grasp for some scripters. When you create a variable for a value class such as a string or a number, you place its literal value in the variable. However, when it comes to an object such as text there are two ways the object can be referenced:

  • As the object itself (a description of the object within the application hierarchy)
  • As the contents within the object

This can be demonstrated in the following examples:

--Assuming there is an insertion point selected 
tell application "Adobe InCopy CC"
set insertRef to item 1 of selection
end tell

The result is a reference to the insertion point, similar to

insertion point 8 of text flow id 622 of document id 2 of application "Adobe InCopy CC"

Add the following line to the script above and the result may surprise you:

set paraRef to paragraph 1 of insertRef

The result is the actual text contained by the paragraph, similar to: “This is the selected text”

If you want your script to do something with an object (such as a paragraph) the script needs to have a reference to the object, not its contents. Change the last statement to read:

set paraRef to object reference of paragraph 1 of insertRef

This returns a text reference in a form similar to:

character 1 to character 14 of story id 622 of document id 2 of application "Adobe InCopy CC"

For the most part, Adobe provides a good scripting implementation for object references. Just about every object in InDesign and InCopy has a property called object reference. Some objects such as story, however, return the object reference by default. For instance, try adding the following to the above example,

set storyRef to parent story of insertRef

The result is an object reference. The issue becomes most noticeable when you want to select the text contents of an object. With the example above, you will get an error if you try to select the parent story (storyRef):

set storyRef to parent story of insertRef
select storyRef

But the following statement does work for the object reference of a paragraph:

set paraRef to object reference of paragraph 1 of insertRef
select paraRef

Try to define a range of characters within the paragraph and the problem becomes even more sticky:

set paraRef to object reference of paragraph 1 of insertRef
set endIndex to length of paraRef - 2
set textRef to (a reference to characters 1 thru endIndex of paraRef)
select textRef

The error posted reads:

 "Adobe InCopy CC got an error: Invalid parameter." number 30477

Not a very helpful error messager.,

If you look up the select command in InCopy’s dictionary, it states that the command is supported by text, character, word, line, text column, paragraph, text style range, and insertion point. The clue is that select works with a character not characters. Could the problem be that the value for textRef as defined is actually a reference to a list of characters, not an object?

For a test, see what is returned for the variable textRef when not a reference:

set textRef to (characters 1 thru endIndex of paraRef)

Knowing the reference is to a list of characters, change the statement to a text reference and it works.

--call to a handler that returns a reference to the selected insertion point
set insertRef to getInsertionPoint()
tell application "Adobe InCopy CC"
set paraRef to object reference of paragraph 1 of insertRef
set textRef to object reference of (text from character 1 to character -2 of paraRef)
select textRef
end tell
--Add handler here. Make sure handler tests for selection, class of selection, and valid paragraph.

ExtendScript

This is one place that JavaScript (ExtendScript) looks easy in comparison to AppleScript. Objects are just that: objects and are referenced by pointers (object reference). For our example, there is no worry about referencing and dereferencing.

main();
function main() {
try {
//call to getInsertionPoint function returns reference to selected insertion point
var insertRef = getInsertionPoint();
var paraRef = insertRef.paragraphs.item(0);
var textRef = paraRef.characters.itemByRange(0, -2);
textRef.select();
}
//Add code for function, make sure you test for selection, constructor.name, and valid paragraph
function getInsertionPoint() {
}

This script is now being added to our InCopy Workflow Scripts collection (downloaded from either the AppleScript or ExtendScript page). Try the script out with stories in InCopy that have styled placeholder text.