Monday, March 20, 2006

 

Filtering Files

On page 540 of the Scripting Reference it says [I've added emphasis to the two key words]:

----------------------------------------

File.openDialog ([prompt][,select])

Opens the built-in platform-specific file-browsing dialog in which a user can select an existing file to open. If the user clicks OK, returns a File object for the selected file. If the user cancels, returns null.

[snip]

select
Optional. A file or files to be preselected when the dialog opens:

[snip]

In Mac OS, a string containing the name of a method defined in the current JavaScript scope that takes a File object argument. The method is called for each file about to be displayed in the dialog, and the file is displayed only when the method returns true.

----------------------------------------

It took me a while to realize that the argument select is not a string but a reference to the function (not method) by name, like this:
function indtFilter(myFile) {
  if (myFile.name.slice(-5) == ".indt") { return true }
  return false;
}

var myFile = File.openDialog("Choose a template.", indtFilter);
if (myFile == null) { exit() }
That works, but put quotes around the name of the function and it won't work -- it shows you all the files.

Change the function definition to a method definition, like this:
File.prototype.indtFilter = function(myFile) {
  if (myFile.name.slice(-5) == ".indt") { return true }
  return false;
}
and you'll get an error that indtFilter is not defined.

OK, so this only affects Mac users, but that's what I am most of the time.

While my observations about the reference are accurate in the above, my assertion that the function indtFilter(myFile) works is valid only in the narrow sense that it is constructed correctly. It has a bug you can drive a bus through (as my brother likes to say).

The problem is that the way I have constructed it denies the user the ability to navigate folders. What's needed is this:
function indtFilter(myFile) {
  if (myFile.constructor.name == "Folder") { return true }
  if (myFile.name.slice(-5) == ".indt") { return true }
  return false;
}
Now, in addition to (in this case) any InDesign templates, the folder items in the file dialog will also be active, allowing the user to navigate the file system.

Wednesday, March 15, 2006

 

Do Away with the Scripts Palette?

For the longest time, I've used a workspace that has two columns of palettes down the right side of the screen so I can have the Scripts palette permanently available. Lately, I've been wondering if there isn't a better alternative because the way I have things eats seriously into document space. So the question arises: can I script my way out of the need to have the scripts palette permanently displayed.

I might not have had this thought at all had it not been for Peter Kahrel mentioning that he uses a script to access recent scripts. Apparently, Peter keeps all his scripts in one folder so, in addition to displaying the recently used scripts he can readily display all the others at the bottom of the menu he throws up.

I have a large number of folders holding scripts -- so large a number that assembling them into a menu would be slow and generally pointless in that many of them are just sitting there waiting to be used only for a special occasion. So, the thought I have is this: Let's build a script that uses a couple of special folders to hold information. One will contain what I'll call the permanently available scripts. Some scripts I use enough that I know that I'll always want quick access to them even if they happen to have temporarly dropped off the most recent list, so I'll put these into a folder named "Always" and they'll always be there -- indeed, any that are in this folder will never appear on the most recent list because they'll be permanently available anyway.

A second folder will hold aliases to the most recently used scripts. Also in there will be a preferences file.

My inital thoughts on what the script that manages all this does is this:

1. If the Recent folder doesn't exist, it creates it and throws up the preferences dialog. I have three preferences in mind:

Number of Recent Scripts
Display Script Label of Selection
Display Palette Folders

The meanings of these will become apparent as we look at the reset of the functions.

2. The script will manufacture a dialog that will display a drop-down menu of selectable script names, starting with the Always scripts then the Recent scripts, and optionally (see prefs) the names of all the folders in the Scripts palette (top level only). If the user chooses one of the script names, the script in question will be run. If the user chooses a folder, the script will present another dialog with that folder name in it.

3. If the prefs ask for it and there is a selection, the script label of the selection will be displayed in a static text field -- this is for info only; it is not intended as a mechanism for changing labels. [Hmmm: I might have second thoughts about this -- what if one of the Always available scripts changed the script label. That would do away with the need for the Script Label palette. Maybe.]

And that's where I am at the moment. Now I need to start on some implementation.

Monday, March 06, 2006

 

What and Where's that Glyph?

You receive a file from a client and some of the characters have the "dreaded pinkness" indicating that a glyph has been used that isn't present in the font you're using. Other characters in the same font do not show the dreaded pinkness, so this is not a case of a missing font but rather a missing glyph issue.

So, how do you find out which glyph it is supposed to be? I used this process:

1. I selected the glyph in my InDesign document.
2. I opened the Info palette.

And that told me that the missing glyph was unicode value 25CF.

To find out what it is supposed to look like, I visited: http://www.unicode.org/charts/ and typed the unicode value into the search.

To find out if any of my fonts had this glyph present, I wrote this quick and dirty script. It relies on the fact that if a glyph is not populated in a particular font and you try to convert it to outlines, you get an error:
//DESCRIPTION: Seek out Fonts with code point populated

codePoint = "\u25CF";
myFonts = app.fonts;
codePresentList = [];
for (j = 0; myFonts.length > j; j++) {
  myDoc = app.documents.add();
  myFrame = myDoc.pages[0].textFrames.add();
  myFrame.geometricBounds = myDoc.pages[0].bounds;
  myFrame.insertionPoints[0].contents = codePoint;
  try {
    myFrame.parentStory.characters[0].createOutlines();
    codePresentList.push(myFonts[j].name);
  } catch (e) {
  // Glyph not present, ignore
  }
  myDoc.close(SaveOptions.no);
}
alert ("Code present in:\r" + codePresentList.join("\r"));
Were the glyph to be present in any significant number of fonts, using an alert to inform the user is not a good idea, but in my case none of the 1140 fonts had the glyph so the alert was tolerable.

I'll come back to this script one day and improve it.

 

Replacing Links

A U2U forum visitor posted a request for a script to replace linked color images with black & white (grayscale, probably) equivalent images using a particular naming scheme. Here's the script I created:
//DESCRIPTION: Replace color linked images with BW alternates

 /*
   Color images have "_cp" in their names; BW have "_bw"
 */

myDoc = app.activeDocument;
myLinks = myDoc.links;
for (j = myLinks.length - 1; j >= 0; j--) {
  myName = myLinks[j].filePath;
  myNewName = myName.split("_cp").join("_bw");
  if (myName != myNewName) {
    // Original link includes "-cp" in name
    myNewImageFile = File(myNewName);
    if (!myNewImageFile.exists) {
     alert ("Can't find file: " + myNewName);
      continue;
    }
    myLinks[j].relink(myNewImageFile);
    myLinks[j].update();
  }
}
It occurred to me having written the script for the situation where the two sets of images are in the same folder, the logic for converting the names will also work if the two sets are segregated into two side-by-side folders that use the same naming trick to distinguish one from the other.

PS: Things have been very hectic lately getting huge jobs out the door, so I've neglected the blog some. Hopefully, this will change now that the jobs are complete.

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