Saturday, September 24, 2005


Swatch Labeler

This is different. I'm working with a client on the other side of the country. I need to communicate colors unambiguously to them. I plan to send a PDF that has a number of elements that look like this:

This is a grouped object in my InDesign document consisting of a rectangle with another rectangle rotated by 30 degrees and pasted into the first. It's the stroke of the pasted rectangle that separates the top left of the first rectangle from the second. Then, there's a two paragraph text frame set to vertically justify which labels the two colors in the two rectangles.

I grew tired of manually updating the names of the colors in the text frame, so I wrote this script to do the job for me. All I have to do is apply swatches to the two rectangles and then run this script:
//DESCRIPTION: Color Swatch Labeller

if ((app.documents.length != 0) && (app.selection.length != 0)) {
 var myGroup = app.selection[0];
 while ( != "Group") {
  myGroup = myGroup.parent;
  if ( == "Application") { errorExit("Selection is not part of a group.") }
 var myRect = myGroup.rectangles[0];
 var myPasted = myRect.rectangles[0];
 var myTF = myGroup.textFrames[0];
 myRE = new RegExp("\\D+(\\d+)\\D+(\\d+)\\D+(\\d+)\\D+(\\d)");
 var myString =;
 myString = myString.replace(myRE, "$1, $2, $3, $4");
 myTF.texts[0].paragraphs[0].characters.itemByRange(0,-2).contents = myString
 myOtherString =;
 myTF.texts[0].paragraphs[1].contents = myOtherString;
} else {

// +++++++ Functions Start Here +++++++++++++++++++++++

function errorExit(message) {
 if (arguments.length > 0) {
  if (app.version != 3) { beep() } // CS2 includes beep() function.
 exit(); // CS exits with a beep; CS2 exits silently.
Let's look closely at the main part of this script. The first while loop identifies the group of interest from the selection. Notice the error message that can be generated within the loop.

There is a potential problem when looking up the parental chain to try to find something: you might reach the top of the chain. But, there is no top as far as InDesign is concerned (I think this is a bug, myself; compare the parent of the top of the hierarchy in the File System object model: it is null, thereby eliminating infinite loops when searching up the parental chain). InDesign's application object is its own parent, so without the test:
  if ( == "Application") { errorExit("Selection is not part of a group.") }
inside the loop, if the selection were not part of a group, the loop would spin endlessly.

OK, in testing that I realized that my script is slightly inadequate in that if you have the text tool active with some text inside the text frame, the script fails to find the group. I need to remedy this by adding the isPureText() method and using it, like this:
 var myGroup = app.selection[0];
 if (myGroup.isPureText()) { myGroup = myGroup.parentStory.textFrames[0].parent }
 while ( != "Group") {
While the script would still have worked had I left off the final .parent, it saves a step. That parent is either a group or not. If not, we're going to get the error anyway. If it is a group, it's the group we're looking for, so we can go right to it.

I haven't bothered any more error checking. This script has a very narrow purpose and so I can just assume that the group I've found is of the right kind. Hence:
 var myRect = myGroup.rectangles[0];
 var myPasted = myRect.rectangles[0];
 var myTF = myGroup.textFrames[0];
I know that these must be right (unless I've lost my mind and I'm running this script on some other group).

Hello! Another use of RegExp. It took me a while to get that string right. I forgot to include the double backslashes. They're needed because the expression is inside a string, so for one of them to get through to my RegExp expression, I need to have two: the first "escapes" the second.

The purpose of the RegExp is to convert a swatch name in the form C=0 M=75 Y=30 K=60 to the form I need it for my caption in the first paragraph of the text frame. "\D+" tells RegExp to seek out any string of one or more non-digits while "\d+" seeks any string of one or more digits. The parentheses provide the mechanism for extracting substrings from the total found string. All I want are the numbers, so I've put the digit strings into parentheses. Then, in the replace() call a couple of lines later, I use $1, $2, etc. to refer to these substrings, and I insert the comma-space separators to get the string into the form I want it. Then it's easy to update the contents of the first paragraph (taking care to avoid the closing return) with the string.

Fortunately, PANTONE colors are named just the way I want them and the second paragraph doesn't have a return, so handling them is easy.

So why am I doing all this? So I can say to my client: I'm planning to use the CMYK mix indicated by the top left caption. It corresponds to the PANTONE (why does PANTONE insist that everybody always SHOUT their name?) color at bottom right. My client can then refer to the PANTONE swatch book and compare what's on screen with what's in the PANTONE book so they can get some sense of what the printed version will look like.

By the way, even I can see that PANTONE 1807 C is not the same as 0, 75, 30, 60. The capture I took was in an intermediate state.

I know you posted this a long time ago, but I am no javascript guru. I was hoping that you could help me with the javascript that would let me select a color box and when I run the script it would simply put the CMYK breakdown next to it. Thanks.
You'd be better off posting this request for help in the Adobe User-to-User InDesign Scripting forum:

I'm up to my eyes at the moment. Sorry.
Post a Comment

<< Home

This page is powered by Blogger. Isn't yours?