Run a JavaScript script.

Run a JavaScript script. The function accepts the complete script or the path to script file.

Predefined objects can only be used in scripts whose text is defined as string (char* or string). Predefined objects cannot be supported in file-based scripts!

If your file-based script contains no relative file references, you can easily read in the file before:

String 	js = string::alloc ();
:
fi = file::open ("yourfile.js", "r"); file::read_str (fi, js); file::close (fi); :
string::release (js);

If you use Javascript, you wish to change some document objects in most cases. Unfortunately you only know the objects ItemRef in cScript. But in Javascript you need the document object itself. To retreive the Javascript object, you have to many things:

Translating a cScript ItemRef into a Javascript object. Before you can execute the script, you have to replace $$PATH$$, $$NAME$$ and $$UID$$ bei their current values:

function main ()
{
    var result = 201;
    for(var n=0;n<app.documents.length;n++)     {         var doc = app.documents [n];
        if ((doc.saved && File (doc.fullName).fullName == File (\"$$PATH$$\").fullName)             ||             (!doc.saved && doc.name == \"$$NAME$$\"))         {             var myFrame = doc.pageItems.itemByID ($$UID$$);
            try             {                 // ... your code                 result = 0;             }             catch (e)             {                 result = 1230;             }             break;         }     }     return result; } main ();

To avoid this, simply call run_script with an non-empty itemRefs list containing the objects you wish to work on.

The red marked line above is created by the function automatically: For every entry of the list, the following variables are defined:

    var gItemRef1 = ...
    var gItemRef2 = ...
    ...

Depending on the classes of the entries (see item::get_class) the appropriate objects of the InDesign® JavaScript Scripting DOM are used here. ItemRefs may come from different documents. Therefor a parallel list of document objects is created too:

    var gDocRef1 = ...
    var gDocRef2 = ...
    ...

The gDocRefs are created automatically from the ItemRefs of the given object list! Finally, two arrays containg the above objects are defined:

    var gItemRefs = [];
    var gDocRefs = [];

The variable gDocument is 0 in most cases, so it is not suitable for the function's object list. However, since every document contains at least one page, you can use the following simple trick to get a defined ItemRef from which the document can be determined.

ItemRef		pageRef	= item::alloc ();
ItemList	li 	= itemlist::alloc ();
document::get_pageref (pageRef, gDocument, 1); itemlist::append (li, pageRef);

The following table shows all supported object types:
ItemRef Type ClassID JavaScript Type
document 0xe01 Document
frame 0x6201 PageItem
hyperlink 0x13501 Link
multistate 0x145d8 MultiStateObject
checkbox 0x1450d Checkbox
radiobutton 0x1450e RadioButton
textbox 0x1450f TextBox
listbox 0x14510 ListBox
combobox 0x14511 ComboBox
signature field0x14512 SignatureField
table 0xb608 Table
bookmark 0x1354c Bookmark
book 0x10001 Book

Javascript can be executed directly from InDesign®. Until InDesign® CC 2019 there was the program ExtendScript Toolkit (ESTK) from Adobe to do that. With InDesign® 2020 the support of ESTK has been deprecated. Older versions of the programme can still be found on the net and work even under Windows. But ESTK is a 32-bit program and will not work on Mac OS X Catalina and later.

The solution proposed by Adobe is to install Visual Studio Code. Adobe provides the ExtendScript Debugger plugin for VS Code. After installing the plugin, you can run and debug your javascripts in VS Code easily.

However, the whole thing does not work with InDesign ® Server. But fortunately each installation of InDesign® Server contains the small program sampleclient, with which you can execute Javascript (without debugging but otherwise very convenient) from InDesign® Server. The procedure is very simple:

  1. From Terminal/Console start InDesign Server with option -port 1234 (or any port number you like).
  2. From a second terminal window call sampleclient yourScript.jsx -host localhost:1234. (Instead of localhost, you can of course control a remote server too. This is especially nice.)
  3. See the servers Terminal/Console window for the result(s).

In addition, with gName="gValue" pairs you can define any number of arguments for you script. Use the following the following instruction to get the value of the parameter "gName" inside your Javascript:

var arg1 = app.scriptArgs.get("gName");

The following Javascript uses cScript to set the current front layer of a document. The desired layer is specified by myArg="Layer 3" in the call to sampleclient.

var myPath = "/Users/paul/Desktop/iddoc.indd";	// Path to your document
var gOptions = app.comet.ping() + ";-1;";
// cScript to execute // If the script is called with non-empty gArgument, // select this layer. // Then write the name of the current layer in the server console. // var script = "int main ()\ {\   String n = string::alloc ();\   \   if (strlen (gArgument)) layer::select (gArgument);\   layer::front_name (n);\   showmessage (\"# Front layer '%s'\", n);\   return 0;\ }";
var layer = app.scriptArgs.get("myArg"); // The argument 'myArg' of sampleclient contains the layer name
app.comet.documentOpen (myPath, true, gOptions); // Open doc app.comet.eval (script, layer, '', gOptions); // Exec script with argument 'layer' app.comet.documentSave (myPath, gOptions); // Save doc app.comet.documentClose (myPath, gOptions); // Close doc

Name Type Default Description
Return int  

0 or ErrorCode

This value indicates wether the script execution was successful or not. This value is not the return value of the script itself! To retreive the return value of the script, use returnType, returnValue, and returnMaxLen.

script_or_path String or char* - Complete script text (JavaScript of course!) or complete path to a JavaScript file
isPath int 0 Does script_or_path contains the JavaScript text or a file path?

0 : script text
1 : path, predefined objects not supported in this case!
showErrorAlert int 1 Show error alert on script errors?

0 : No
1 : Yes
flags int 0 The undo behavior of the script:

0 : Each script statement gets a separate undo step.

2 : Push the entire script as a single regular undo step. If an error occurs, roll back to the beginning of the script request that generated the error.

4 : Similar to 2, however faster because we don't snapshot each script request. If an error occurs, we roll back to the beginning of the entire script.

6 : Push the entire script as a single auto-undoable step.
returnType int 0 Type of returnValue.

0 : returnValue ignore
kInt : returnValue is of type int*
kFloat : returnValue is of type float*
kString : returnValue is of type String or char*

Attention: This is the type of returnValue, NOT the type of value returned by the script! If you don't know the scripts return type (or it uses a type not defined above), you may use kString, anyway. For later uses of this value, you have to convert into the appropriate type (val, fval, ...).
returnValue int*, float*, String or char* 0 Variable for the return value of the script

0 : ignore
returnMaxLen int 0 Only used in case of returnType = kString and when the return type is of type char*. Set it to the number of bytes allocated for returnValue.

0 : don't care, I have allocated enough space.
itemRefs ItemList - ItemRefs which are converted to global variables in your JavaScript, see Predefined Objects This parameter creates JavaScript variables named gItemRef1, gItemRef2, etc..
When these ItemRefs are objects inside a document, they also create the according document variables gDocRef1, gDocRef2, etc.. Furthermore, two global arrays names gItemRefs and gDocRefs are created containing all objects.
The ItemRefs are being converted to their appropriate JavaScript objects. Please note that ItemRefs pointing to documents always have to be defined (not 0)(gDocument is 0 in most cases.). The following table shows which ItemRef types are supported and to which JavaScript types they get converted.
ItemRef Typ ClassID JavaScript Typ
document 0xe01 Document
frame 0x6201 PageItem
hyperlink 0x13501 Link
multistate 0x145d8 MultiStateObject
checkbox 0x1450d Checkbox
radiobutton 0x1450e RadioButton
textbox 0x1450f TextBox
listbox 0x14510 ListBox
combobox 0x14511 ComboBox
signature field 0x14512 SignatureField
table 0xb608 Table
bookmark 0x1354c Bookmark
book 0x10001 Book
@Version 2.1, R 1456, 29. Juli 2009
Parameter returnType, returnValue, returnMaxL since v3.4 R7021, 19. Nov. 2014
Parameter itemRefs since v4.1 R13700, 15. Sep. 2016
Undo-Scope im Parameter flags since v4.1.6 R25778, 10. Sep 2019
Preconditions
#include "internal/types.h"

The example shows how your JavaScript can easily access the current frame.

int main ()
{
    ItemList myframes = itemlist::alloc ();
itemlist::append (myframes, gFrame); run_javascript ("gItemRef1.contentType=ContentType.UNASSIGNED", 0, 1, 0, 0, 0, 0, myframes);
return 0; }

Show the name of the current front document:

int main ()
{
    char		js[5000];
strcat (js, "if (app.documents.length != 0)\n"); strcat (js, "{\n"); strcat (js, " alert (app.activeDocument.name);\n"); strcat (js, "}\n"); strcat (js, "else\n"); strcat (js, "{\n"); strcat (js, " alert (\"Please open a document.\");\n"); strcat (js, "}\n");
run_javascript (js);
return 0; }

Show the name of the current front document using a file based script:

int main ()
{
    char		js[5000];
strcat (js, "$DESKTOP/ttt.js");
run_javascript (js, 1);
return 0; } ttt.js must exist on your desktop:
if (app.documents.length != 0) { alert (app.activeDocument.name); } else { alert ("Please open a document."); }

Four variants of a string-based script to query different return types:

#include "internal/types.h"
char * get_script (int returnType) { char * js = alloc (10000);
strcpy (js, "\n"); strcat (js, "function main ()\n"); strcat (js, "{\n"); if (returnType == kInt) strcat (js, " return 123456789;\n"); else if (returnType == kFloat) strcat (js, " return 3.1415926;\n"); else if (returnType == kString) strcat (js, " return \"Pi = 3.1415926\";\n"); strcat (js, "}\n"); strcat (js, "\n"); strcat (js, "main ();\n");
return js; }
int run_script (int returnType) { char * js = get_script (returnType); int vi = -1199; float vf = -11.99; char vs [4000]; int * adr = 0; int res;
if (returnType == kInt) adr = &vi; else if (returnType == kFloat) adr = &vf; else if (returnType == kString) adr = vs;
res = run_javascript (js, 0, 0, 0, returnType, adr, 4000);
if (returnType == kInt) wlog ("", "JS (int) : result = %d, retval = %d\n", res, vi); else if (returnType == kFloat) wlog ("", "JS (float) : result = %d, retval = %f\n", res, vf); else if (returnType == kString) wlog ("", "JS (char*) : result = %d, retval = '%s'\n", res, vs); else wlog ("", "JS : result = %d\n", res);
release (js);
return res; }
int main () { run_script (0); run_script (kInt); run_script (kFloat); run_script (kString);
return 0; }

Four variants of a file-based script to query different return types. (Use the above Javascript script code for this files.)

#include "internal/types.h"
int run_script (int returnType) { char path [4096]; int vi = -1199; float vf = -11.99; char vs [4000]; int * adr = 0; int res;
strcpy (path, "$DESKTOP/js"); if (returnType == kInt) { adr = &vi; strcat (path, "_int"); } else if (returnType == kFloat) { adr = &vf; strcat (path, "_float"); } else if (returnType == kString) { adr = vs; strcat (path, "_string"); } strcat (path, ".jsx");
res = run_javascript (path, 1, 0, 0, returnType, adr, 4000);
if (returnType == kInt) wlog ("", "JS (int) : result = %d, retval = %d\n", res, vi); else if (returnType == kFloat) wlog ("", "JS (float) : result = %d, retval = %f\n", res, vf); else if (returnType == kString) wlog ("", "JS (char*) : result = %d, retval = '%s'\n", res, vs); else wlog ("", "JS : result = %d\n", res);
return res; }
int main () { run_script (0); run_script (kInt); run_script (kFloat); run_script (kString);
return 0; }

Using the itemRefs parameter, we show all left-top corners of all frames in a document inside alert boxes.

int main()
{
    char 		js[5000];
    int 		i;
    ItemList 	allFrames;
allFrames = itemlist::allframes(); strcat(js, "for (var i = 0; i < gItemRefs.length; i++) {\nalert(gItemRefs[i].geometricBounds[1] + \"|\" + gItemRefs[i].geometricBounds[0]) }");
run_javascript(js, 0, 1, 0, 0, 0, 0, allFrames);
itemlist::release(allFrames);
return 0; }

Remove any watermark from a document.

ATTENTION : The most common usage of the watermark is the watermark of the Developer Edition of InDesign® Servers. \ span[red]{Please consider the license terms for using the Developer Edition of InDesign® Server!}

int main ()
{
    ItemRef		pageRef		= item::alloc ();
    ItemList	li 			= itemlist::alloc ();
document::get_pageref (pageRef, gDocument, 1); itemlist::append (li, pageRef); run_javascript (   "gDocRef1.watermarkPreferences.watermarkVisibility = false;",   0, // Anweisung ist KEINE Datei   0, 0, // Keine Fehlermeldung, kein Debugger   0, 0, 0, // Kein Rückgabewert   li); // Objektliste. Aus pageRef wird gDocRef1 automatisch deklariert
return 0; }

Replace a text in the complete document.

String get_js (char * search, char * repl)
{
    String 		s = string::alloc ();
string::append (s, "var doc = gDocRef1;\n"); string::append (s, "app.findGrepPreferences = NothingEnum.nothing;\n"); string::append (s, "app.changeGrepPreferences = NothingEnum.nothing;\n");
string::append (s, "app.findChangeGrepOptions.includeFootnotes = true;\n"); string::append (s, "app.findChangeGrepOptions.includeHiddenLayers = false;\n"); string::append (s, "app.findChangeGrepOptions.includeLockedLayersForFind = false;\n"); string::append (s, "app.findChangeGrepOptions.includeLockedStoriesForFind = false; \n"); string::append (s, "app.findChangeGrepOptions.includeMasterPages = false;\n");
string::append (s, "app.findGrepPreferences.findWhat = '%s'; \n", search); string::append (s, "app.changeGrepPreferences.changeTo = '%s';\n", repl); string::append (s, "doc.changeGrep();\n");
string::append (s, "app.findGrepPreferences = NothingEnum.nothing; \n"); string::append (s, "app.changeGrepPreferences = NothingEnum.nothing;\n");
return s; }
int main () { ItemRef pageRef = item::alloc (); ItemList li = itemlist::alloc (); String js = get_js ("e", "ttt");
document::get_pageref (pageRef, gDocument, 1); itemlist::append (li, pageRef);
run_javascript (js, 0, 1, 0, 0, 0, 0, li); string::release (js);
return 0; }

See Also
comet.runJavaScript

Alphabetic index HTML hierarchy of classes or Java