How to Write an InDesign Call On Idle Script

callOnIdle

When my son was 4, he came into our bedroom and woke us up in the middle of the night, and informed us: “Now, I want to do some drawing.” We had to tell him that the middle of the night was for sleeping, and it was not the right time to start drawing.

Similarly, when writing InDesign ExtendScript, there is a right time and a wrong time to perform certain operations. Some functions can cause InDesign to crash when called at the wrong time.

This post presents a little helper function, callOnIdle, for InDesign ExtendScript. It should come in handy for intermediate ExtendScript developers struggling with InDesign application and document events.

Who is Kris Coppieters?

Our guest developer post this week is by Kris Coppieters, an accomplished software-engineer and coach. He designs and develops innovative software solutions. Kris can be reached at Rorohiko. You can read more about Kris on his LinkedIn profile, or on his blog.
— Erin Finnegan, Community Engineer, Adobe

Some scripts need to monitor and react to what the user is doing in the host application. In ExtendScript, this is handled with an event model.

Scripts can ask to be notified about interaction from the ‘outside world’ by way of event handler functions.

This means that InDesign can be set up to call an ExtendScript function when something interesting happens.

For example, below are the Document events displayed in the ExtendScript DOM viewer. (they are listed under the ‘Document - Class’ section.) Scripts can listen to these events and react whenever they occur.

The problem

ExtendScript is not ‘native’ to InDesign. It was ‘added on’ later in InDesign’s development. As a result, the integration is not always seamless, and one has to be very careful when handling many of these events.

When writing JavaScript code in the browser, there is an expectation that you can do pretty much anything. Even if your script fails, the browser isn’t supposed to crash.

This expectation isn’t true when running InDesign ExtendScript. There are many ways that scripts can crash the host application. For example, some events in InDesign are fired while the app is already in the middle of handling an operation, and making changes to the document during this time can generate errors and crashes.

I once wrote an InDesign script component for a time tracking system. Each time the user opened and closed the document, the script needed to embed a timestamp and other metadata into the document. A BEFORE_CLOSE event handler seemed to be the obvious solution. But the metadata was never included in the saved document and further experiments to try and make it work would cause InDesign to crash.

Here is some code that illustrates this problem:

Solutions

There are a few potential solutions.

Some of these events are cancelable. One course of action is to cancel the operation from the event handler, perform the necessary tasks, and then re-issue the operation. I am not covering that technique here.

Another solution is to delay modifying or accessing the document or the application until InDesign has completed the task that triggered the event handler. Then, when InDesign becomes idle, it is safe to access the document or application.

The callOnIdle function presented here allows you to easily do just that. This source code is in the public domain.

The code below is heavily commented, and I tried to pay attention to layout and readability to help explain how it all works. I encourage you to study the source code.

An Example

It is not well documented, but when handling Document.AFTER_OPEN, you should refrain from making scripted changes to the document from the handler function. If you do, InDesign won't crash, but the debug build of InDesign will report errors. This indicates it is a no-no, and can lead to crashes when using InDesign with additional plug-ins installed.

Here is a better way to do it:

Next Steps

Because this area is a deep and complex subject, this post is a bit of a whirlwind visit.

While writing, I found myself itching to explain many additional aspects, but if I’d give in, I’d end up writing a whole book instead of a short post.

If you want to learn more about this, or if you want some help integrating this into your own scripts, there are a few things you can do.

  • You can come to the Creative Developer Summit in New Orleans on June 8.I will be there, and I will be offering some free consultations during the Creative Pro Week. These will be first come, first served and time slots are limited. Come and pick my brain.
  • I teach and help design this kind of stuff for a living. If you’re stuck on a difficult project, need something explained, need some debugging, or need some difficult concepts explained, feel free to reach out to me at kris@rorohiko.com
  • I occasionally write about automating the Creative Suite and ExtendScript on my personal blog.

Originally published at gist.github.com.