Below a method to implement an efficient subroutine library with APIDToolAssistant and InDesign CS3/CS4. If you have a large script, and use only a single .spln file, you cause InDesign to re-parse the whole script every time an event needs to be processed.
To avoid unnecessary reparsing, you can store a whole collection of subroutines in a separate .spln, load that .spln just once, and then call the subroutines and functions as needed.
There are many variations on the theme - what's shown here is just one approach.
First piece of the puzzle: if you have multiple .spln files loaded, they can call 'into' each other as long as they share the same component ID. So, when building a subroutine library, you need to make sure it uses the same component ID as your main .spln.
Here's a step-by-step example (assuming APID ToolAssistant is installed):
1) open APIDTemplate, and create a scripted plugin template file (say
MyPlugin); save it to your desktop.
2) open APIDTemplate again, and now create a scripted plugin template file for the library (say
MyLibrary); use the exact same password and copyright string as what you used for
MyPlugin. Save it to your desktop.
Switch to
MyLibrarySourceCSx.indd (where
x = nothing,
2,
3, or
4 - it depends on what version of InDesign you are using). Make the Active Page Item Developer palette visible with the proxy page item selected.
Clear the list of subjects and enter
loadLibrary in the event filter (you can concoct pretty much any other event name -
loadMyNiceLib would work just as well, but I picked
loadLibrary because it describes what the event will do).
Now select the page item below the proxy item, and inspect the start of the attached script code - it should look like
Code:...
kScriptName = "MyLibrary";
kCompiledPassword = "...";
...
Add a line to it so it reads:
Code:...
kScriptName = "MyLibrary";
kComponentIDScriptName = "MyPlugin";
kCompiledPassword = "...";
...
Scroll further down and change the line (which occurs twice - you need to change both of them):
Code:...
var theComponentName = kScriptName + ";" + kCompiledPassword + ";" + kCopyright;
...
into
Code:...
var theComponentName = kComponentIDScriptName + ";" + kCompiledPassword + ";" + kCopyright;
...
Click in the pasteboard area.
This change now forces the library to use
MyPlugin;password and other stuff as its component ID instead of
MyLibrary;password and other stuff - in other words: it now uses the same component ID as the main MyPlugin.
Open the
MyLibrary.jsx file and enter the following code:
Code:alert("loading library");
if (typeof gLibrary == "undefined")
{
gLibrary =
{
function1: function(x) { return x + 1; },
function2: function(x,y) { return x+y; }
};
}
This code will create a global variable
gLibrary which contains an object with a set of functions. You can do anything similar - the main idea is to create some global object that carries your subroutines and functions.
The typeof setup (courtesy of Harbs) is there to test for the existence of
gLibrary without ever mentioning
var gLibrary;. By avoiding
var gLibrary;, through a JavaScript quirk, we guarantee that
gLibrary is truly global - even if the code above is wrapped by APID in some unseen curly brackets.
Otherwise, if the code above is actually wrapped in some invisible outer curly braces (as some APID versions do), the mere mention
var gLibrary; would make
gLibrary local to this invisible outer code block - and it would disappear from memory at the end of the block.
The
alert allows us to notice when this script code is executed - the idea is that it will only be executed once.
Click the 'Select this frame to compile a release version of MyLibrary.spln (with componentId)' page item to compile the library into a .spln. This .spln is pretty 'inert' - it won't do anything by itself.