Ausführen eines JavaScript-Skriptes.

Ausführen eines JavaScript-Skriptes. Dem Aufruf kann der komplette Skripttext oder der Pfad auf eine Skriptdatei übergeben werden.

Vordefinierte Objekte können nur in Skripten verwendet werden, deren Text als String (char* oder String) definiert ist. In dateibasierten Skripten können vordefinierte Objekte nicht unterstützt werden!

Enthält Ihr dateibasiertes Skript keine relativen Dateiverweise, können Sie das Skript mit folgenden Zeilen leicht vorher einlesen:

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

Wenn Sie aus cScript ein Javascript aufrufen, wollen Sie dort in aller Regel irgendein Dokument-Objekt bearbeiten. Das Objekt selbst kennen Sie aber nur über seine cScript-spezifische ItemRef. Im Javascript hilft diese Referenz nicht weiter. Hier benötigen Sie ganz andere Objekte. Um das Javascript ausführbar zu machen, muß dort also zuerst einmal das Dokument, in dem sich das Objekt befindet, gesucht werden. Das geht über den Pfad (oder bei neuen Dokumenten auch über Namen) des Dokumentes. Haben Sie das Dokument, kann dort (mit etwas Kenntnis der InDesign® JavaScript Scripting DOM) das Objekt ermittelt werden. Das ist mit einigem Aufwand verbunden:

Das Beispiel zeigt, wie Sie eine cScript-ItemRef in ein Javascript-Objekt umwandeln können. $$PATH$$, $$NAME$$ und $$UID$$ müssen vor der Ausführung durch aktuelle Werte ersetzt werden:

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 ();

Das alles können Sie sich sparen, wenn Sie der Funktion run_javascript im Parameter itemRefs eine Liste der Objekte mitgeben, die Sie im Javascript bearbeiten wollen.

Die oben rot hinterlegte Zeile erzeugt die Funktion dann selbstständig : Für die Einträge der Liste werden jeweils die Variablen

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

angelegt. Die Funktion entscheidet dabei anhand der Objektklasse (siehe item::get_class) selbst, wie und woher das Objekt in der InDesign® JavaScript Scripting DOM definiert werden muß. Da die Objekte der Liste itemRefs aus verschiedenen Dokumenten stammen können, werden parallel zu den Einträgen gItemRef~ noch die Variablen

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

erzeugt, die jeweils auf das Dokument der Objekte 1, 2, ... zeigen. Die gDocRefs werden also automatisch aus den ItemRefs der übergebenen Objektliste erzeugt! Zum Schluß werden noch zwei globale Arrays mit den Namen

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

erzeugt, die alle entsprechenden Objekte noch einmal enthalten.

Die Variable gDocument ist in den meisten Fällen 0. Sie eignet sich also nicht für die Objektliste der Funktion. Da aber jedes Dokument mind. eine Seite haben muß, können Sie sich mit folgendem einfachen Trick ein definiertes ItemRef holen, aus dem das Dokument ermittelt werden kann.

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

Die folgende Tabelle zeigt, welche ItemRef-Typen unterstützt werden, und in welchen JavaScript-Typ sie konvertiert werden:

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

Javascript kann direkt von InDesign® ausgeführt werden. Bis InDesign® CC 2019 gab es dazu das Programm ExtendScript Toolkit (ESTK) von Adobe. Mit InDesign® 2020 wurde der Support von ESTK eingestellt. Ältere Versionen des Programmes sind noch im Netz zu finden und funktionieren auch noch unter Windows. Aber ESTK ist ein 32-Bit-Programm und auf dem Mac ist mit Catalina Schluß mit ESTK.

Die von Adobe vorgeschlagene Lösung ist die Installation von Visual Studio Code. Adobe stellt für VS Code das Plugin ExtendScript Debugger zur Verfügung. Nach der Installation des Plugins können Sie Ihre Javascripte hier bequem ausführen und debuggen.

Leider funktioniert das Ganze aber nicht mit InDesign® Server. Glücklicherweise enthält jede Installation von InDesign® Server das kleine Programm sampleclient, mit dem Sie Javascript (zwar ohne Debugger aber ansonsten sehr bequem) von InDesign® Server ausführen lassen können. Das Vorgehen ist sehr einfach:

  1. Starten Sie InDesign Server® von Terminal/Konsole mit der Option -port 1234 (oder einer beliebigen anderen Port-Nummer)
  2. In einem zweiten Konsolenfenster starten Sie sampleclient mit Ihrem Script und der Angabe -host localhost:1234. (Statt localhost können Sie natürlich auch einen entfernten Server steuern. Das ist besonders schön.)
  3. Im Konsolenfenster des Servers sehen Sie die Antworten des Servers.

Zusätzlich können Sie sampleclient mit einer beliebigen Anzahl von Key/Value-Paaren der Form gName="gValue" aufrufen. Auf die so gemachten Festlegungen können Sie dann in Ihrem Javaskript zugreifen. Im folgenen Beispiel würde arg1 den Wert "gValue" bekommen:

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

Das folgende Javascript setzt mit Hilfe von cScript den aktuellen Frontlayer eines Dokumentes. Die gewünschte Ebene wird dabei mit myArg="Ebene 3" im Aufruf von sampleclient festgelegt.

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 Typ Default Beschreibung
Return int  

0 oder Fehlercode

Der Wert ist lediglich eine Aussage darüber, ob das Skript fehlerfrei ausgeführt werden konnte oder nicht. Der Wert ist nicht der Wert eines mglw. im Skript definierten return. Den return-Wert des Skriptes können Sie mit Hilfe der Variablen returnType, returnValue, returnMaxLen abfragen.

script_or_path String oder char* - Skriptcode (ExtenScript JavaScript) oder vollständiger Dateipfad einer ExtentScript- (jsx) oder UXP-Javascript (idjs) Datei.

Bitte beachten Sie, dass ExtentScript und UXP unterschiedliche Syntax haben. Eine automatische Unterscheidung beider Skripttypen ist nur bei der Angabe von Dateipfaden möglich (und wird über die Dateiendungen gemacht). Wenn Sie ein UXP-Skript als String vorliegen haben, können Sie die Funktion run_uxpscript verwenden.

isPath int 0 Ist der Text JavaScript oder ein Dateipfad?

0 : Text
1 : Pfad, vordefinierte Objekte werden in diesem Fall nicht unterstützt!
showErrorAlert int 1 Bei Skriptfehlern eine Fehlernachricht zeigen?

0 : Nein
1 : Ja
flags int 0 Hinweise zur Ausführung. Mehrere Angaben könnne addiert werden. Die Beschreibungen sind direkt aus dem InDesign-SDK von Adobe entnommen.

1 : Indicates whether to load script into debugger for execution

0 : Push each script request as 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 Datentyp des nachfolgenden Parameters returnValue.

0 : returnValue ignorieren
kInt : returnValue ist int*
kFloat : returnValue ist float*
kString : returnValue ist String oder char*

Achtung: Die Angabe bezieht sich auf den Datentyp von returnValue, nicht auf den Datentyp, den das return des Skriptes tatsächlich verwendet. Wenn Sie diesen Datentyp nicht kennen (oder das Skript einen anderen Datentyp als einen der drei oben definierten zurückgibt), können Sie auch kString verwenden. In diesem Fall erhalten Sie das Ergebnis immer. Sie müssen dieses Ergebnis dann aber bei Bedarf in den entsprechenden Datentypen umrechnen (val, fval, ...).
returnValue int*, float*, String oder char* 0 Variable für den return-Wert des Scripts

0 : ignorieren
returnMaxLen int 0 Die Angabe wird nur im Fall von returnType = kString und wenn der Datentyp ein char* ist verwendet und gibt die maximale Länge für returnValue an (Das Byte für die abschließende 0 ziehen wir selber ab.)

0 : beliebig (Ich habe genügend Speicher allokiert!)
itemRefs ItemList - ItemRefs, die im JavaScript als globale Variablen zur Verfügung gestellt werden, siehe Vordefinierte Objekte
... int, value -,-

[Ab v4.3 R36514, 12. April 2025] Beliebig lange (auch leere) Liste von Paaren aus Datentyp und Wert. Die Angaben werden der Reihe nach als arg1, arg2, ... an die Skriptausführung weitergegen und können im Skript etwa mit folgener Anweisung erfragt werden:

app.scriptArgs.get("arg1");

Zusätzlich wird in arg0 der aktuelle Skripfad übergeben. Ist das Skript als String definiert, enthält arg0 den Wert "String"

Erlaubt sind folgende Typ/Wert-Paare:

Typ Typ des Wertes
0 kInt int
1 kFloat float
2 kString char* oder String
Preconditions
#include "internal/types.h"
#include "internal/types.h"

Das Beispiel zeigt, wie JavaScript auf sehr einfache Weise auf den aktuellen Rahmen zugreifen kann.

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; }

Zeige den Namen des aktuellen Dokumentes.

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; }

Das selbe können Sie auch mit einem JavaScript aus einer Datei machen.

int main ()
{
    char		js[5000];
strcat (js, "$DESKTOP/ttt.js");
run_javascript (js, 1);
return 0; } ttt.js muss sich auf dem Desktop befinden und etwa folgenden Inhalt haben :
if (app.documents.length != 0) { alert (app.activeDocument.name); } else { alert ("Please open a document."); }

Vier Varianten eines string-definierten Skriptes werden ausgeführt und jeweils die Rückgabewerte ins Log geschrieben.

#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; }

Vier Varianten eines Datei-definierten Skriptes werden ausgeführt und jeweils die Rückgabewerte ins Log geschrieben. (Sie können den Scriptcode aus dem vorangegangenen Beispiel für die verschiedenen Skriptdateien verwenden.)

#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; }

Das Beispiel demonstriert eine einfache Verwendung vordefinierter Objekte in run_javascript : Sammle alle Rahmen des Dokumentes und laß dann von einem Javascript die Koordinaten der jeweiligen linken oberen Ecken mit einem 'alert' anzeigen.

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; }

Entferne das Wasserzeichen des Dokumentes.

ACHTUNG : Häufigste Anwendung des Wasserzeichen ist das Wasserzeichen der Developer-Edition des InDesign® Servers. Bitte beachten Sie die Lizenzbestimmungen zur Nutzung der Developer-Edition des InDesign® Servers!

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; }

Ersetze im gesamten alle Vorkommen eines Textes

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; }

Ermittle den Wert eine benuzerdefinerten Textvariable.

#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; }

Das Skript führt das Javascript a1.jsx ihres Schreibtisches mit den zusätzlichen Argumenten aus, die direkt im cScript festgelegt werden und vom Javascript a1.jsx verwendet werden können.

#include "internal/types.h"br/>
int main()
{
    run_javascript (
     	"$DESKTOP/a1.jsx", 1,	// is path
     	1, 3,					// show error alert, undo entire script
     	0, 0, 0,
     	0,						// no addtional items
     	kString, 	"XXXX",
     	kInt,		123,
     	kFloat,		3.1415926,
     	kString,	0);			// defines the value "NULL" in the Javascript
return 0; }

Das Javascript demonstriert, wie Argumente aus Aufrufen von run_javascript im Javascript ausgewertet werden können.

function main ()
{
    alert (app.scriptArgs.get("arg0"));
    alert (app.scriptArgs.get("arg1"));
    alert (app.scriptArgs.get("arg2"));
    alert (app.scriptArgs.get("arg3"));
    alert (app.scriptArgs.get("arg4"));
    alert (app.scriptArgs.get("arg5"));
    alert (app.scriptArgs.get("arg6"));
return 0; }
main ();

Seit
Version 2.1, R 1456, 29. Juli 2009
Parameter returnType, returnValue, returnMaxL seit v3.4 R7021, 19. Nov. 2014
Parameter itemRefs seit v4.1 R13700, 15. Sep. 2016
Undo-Scope im Parameter flags seit v4.1.6 R25778, 10. Sep 2019
Skript-Argumente arg1, arg2, ... ab v4.3 R36514, 12. April 2025
Siehe auch
comet.runJavaScript
comet.runJavaScript

Alphabetic index HTML hierarchy of classes or Java