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 field | 0x14512 | 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:
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.
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 |
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; }
Determine the value of a user-defined text variable.
#pragma plain // @ICONID 413
#include "internal/types.h" #include "internal/text.h"
// Ask for the content of this variable. Since this // script is for demonstrations purposes only, // we only support CUSTOM_TEXT_TYPE (Benutzerdefinierter Text) here! // char stVarName [] = "var1 ";
// The javascript template // char jsText[] = "\n\ function main ()\n\ {\n\ var varval = '';\n\ var textvar = gDocRef1.textVariables.itemByName ('$VARNAME');\n\ \n\ try\n\ {\n\ if (textvar.variableType == VariableTypes.CUSTOM_TEXT_TYPE)\n\ varval = textvar.variableOptions.contents;\n\ else\n\ varval = 'Unsupported variable type';\n\ \n\ } \n\ catch (err)\n\ {\n\ varval = 'Variable $VARNAME is not defined.'\n\ }\n\ return varval;\n\ }\n\ \n\ main ();\n\ ";
int main() { ItemRef pageRef = item::alloc (); ItemList li = itemlist::alloc (); String js = string::alloc (); String varval = string::alloc ();
// Need this to identify the current front document // document::get_pageref (pageRef, gDocument, 1); itemlist::append (li, pageRef);
// Prepare the JavaScript // string::set (js, jsText); string::replace (js, "$VARNAME", stVarName, 0, 1);
// Run the script // run_javascript (js, 0, 1, 0, kString, varval, 0, li);
// Do something with the result // showmessage (varval); return 0; }
Alphabetic index HTML hierarchy of classes or Java