Menüeinträge (sprachunabhängig) per Script aufrufen.

Ein Quickie zum Thema Menüs in JavaScript.

Menüs in InDesigns Objektmodell

Wenn man per Script an die Menüs von InDesign ran will, muss man zwischen diesen Dingen unterschieden:

  • menus
  • menuElements
  • menuItems
  • menuActions

menus

Unter menu fallen alle Menüs, also auch alle Paletten-, Sub- und Kontextmenüs. Davon gibt es eine ganze Menge.

Falls Sie wissen wollen, wie viele, lassen Sie dieses Script laufen:

main();
 
function main() {
  var menus = app.menus.everyItem().getElements();
  for ( var n = 0; n < menus.length; n++ ) $.writeln( menus[n].title );
}

Die ersten 10 sind:

Main
Absatzbedienfeldmenü
Absatzformat-Steuerungsbedienfeldmenü
Absatzformatbedienfeldmenü
Allgemeines Kontextmenü
Änderungsinformationen-Bedienfeldmenü
Animationsbenutzeroberflächen-Bedienfeldmenü
Artikelbedienfeldmenü
Aufgabenbedienfeld-Kontextmenü
Aufgabenbedienfeldmenü

menuItem vs menuElement

Grob gesagt ist ein menuElement alles, was in einem Menü zu sehen ist und ein menuItem ist ein Befehl, der in einem Menü zu sehen ist.

Submenüs und Trennstriche sind also menuElements, aber keine menuItems.

Wenn ich wissen will, ob ein Menüentrag einen Haken hat, muss ich das menuItem inspizieren, nicht das menuElement.

menuAction

Zu jedem menuItem gehört eine menuAction, als die Aktion, die gestartet wird, wenn jemand den Befehl aufruft.

Um die Aktion zu finden, gibt es die Eigenschaft menuItem.associatedMenuAction

Menübefehle in der Baumstruktur

Die Hauptmenüleiste oben ist das „Main“-Menü.

Die Einträge im Menü werden am leichesten über ihren Namen adressiert. Wenn ich also per Script ein Dokument schließen will, kann ich statt direkt

app.activeDocument.close( SaveOptions.ASK );

auch über den Menüeintrag gehen:

app.menus.item("Main").menuElements.item("Datei").menuItems.item("Schließen").associatedMenuAction.invoke()

Man sieht schon das Problem: Wenn ich dieses Script in einem englischen InDesign laufen lasse, fliegt es mit um die Ohren, weil es kein menuElement mit dem Namen „Datei“ gibt. Hier müsste es „File“ heißen.

Sprachunabhängige Identifier

Als Lösung hat jeder Eintrag einen sprachunabhängigen Identifier (, der allerdings nicht so ganz ohne weiteres rauszufinden ist).

Die Codezeile von eben würde dann so aussehen:

app.menus.item("$ID/Main").menuElements.item("$ID/&File").menuItems.item("$ID/&Close").associatedMenuAction.invoke();

Aber woher weiß man das, was man hier eingeben soll?

Die sprachunabhängigen Identifier rausfinden

Im ScriptingGuide von Adobe wird die Funktion app.findKeyString als Lösungsansatz genannt. Was genau die macht, habe ich mir nie die Mühe gemacht rauszufinden.

Mein Script, mit dem ich mir eine Textdatei (auf dem Schreibtisch) erstelle, in der zu allen Menüeinträgen die möglichen Identifier stehen, ist dieses hier:

  var f = File("~/Desktop/ID_Menus.txt");
  f.encoding = "UTF-8";
  f.open("w");
main();
  f.close();
 
function main() {
  var ms = app.menus.everyItem().getElements();
  for (var n = 0; n < ms.length; n++) {
    $.writeln( ms[n].name );
 
    f.writeln("MenuItem\tTitle\tlocale_independent\r");
    get_elements( ms[n], ms[n].name );
    f.writeln( "\r-------------------------------------------------------------\r");
   }
}
function get_elements( menu, father ) {
  var list = "";
  var ms = menu.submenus;
  var mis = menu.menuItems;
  var mnstr = getKeystring ( menu.name );
  f.writeln( "\r\rMenu: "  + father + " ~= " + mnstr );
 
  for (var n = 0; n < ms.length; n++) { var title = ms[n].title; if (title != "Apple") { f.writeln(father + " > " + ms[n].name + "\t" + title + "\t" + getKeystring( title ));
      get_elements( ms[n], father + " > " + ms[n].name );
    }
  }
 
  for (var n = 0; n < mis.length; n++) { var mi = mis[n]; if (mi.isValid) { var title = mi.title; f.writeln(father + " > " + mi.name + "\t" + title + "\t" + getKeystring( title ));
      }
  }
  return ;
}
 
function getKeystring( s ) {
  var myKeyStrings = app.findKeyStrings(s);
  myString = "";
  if(myKeyStrings.constructor.name == "Array"){
    for(var myCounter = 0; myCounter < myKeyStrings.length; myCounter ++){
      myString += myKeyStrings[myCounter] + ", ";
    }
  } else {
    myString = myKeyStrings;
  }
  return myString;
}

Lassen Sie das in Ihrer InDesign-Version laufen und nach ziemlich langer Zeit (es gibt sehr sehr sehr viele Menübefehle in InDesign), ist die Textdatei erstellt.

Ein exemplarischer Ausschnitt:

Main > File > Open… &Open… $ID/&Open…, $ID/Open…
Main > File > Browse in Bridge… Bro&wse in Bridge… $ID/FileForBrowse,
Main > File > Close &Close $ID/&Close
Main > File > Save & $ID/&Save, $ID/#DIALOG_ConversionWarn_Save…_&, $ID/UICustMenusSetSave

Wie Sie sehen, gibt es für manche Begriffe (i.e. Menü-Item-Titel) mehrere mögliche Identifier.
Ich kenne in diesem Fall keinen besseren Weg als einen „intelligent guess“ und Ausprobieren.