System Events
The System Events application lets you automate the GUI in any application. You can see some examples in AppleScript Wikibook.
var se = Application('System Events')
se.keystroke('Hello')
se.keystroke('a', { using: 'command down' })
AppleScript Equivalent: tell application "System Events" to start the current screen saver
However, the verb here is start, and the current screen saver is the noun. So converting that to JavaScript-speak makes it look like this:
se.start(se.currentScreenSaver)
Assuming you have a VPN service called "MyVPN" in the network preferences. You can use JXA to tell your computer to connect to it.
AppleScript Equivalent: tell application "System Events" to disconnect service "MyVPN" of network preferences
se.connect(se.networkPreferences.services["MyVPN"])
First you must enable osascript
access under Security & Privacy ➡️ Accessibility in Settings. The only way to do this is to use a front-end tool tccutil.py
to add the entry (since osascript
is not a .app
bundle).
Download the Python script and execute it like so:
sudo python tccutil.py -i /usr/bin/osascript
Note that you also must add any in-between applications, like tmux
or screen
if you expect osascript to work from there.
Also back in Settings, be sure to add Terminal.app which you can do normally.
Understand that the top menu can only be grabbed with System Events and you must activate the application for the menu you want before you can click the item. If you are doing GUI interactions, always think of the steps that you would take normally. Additionally, you may want to find the quickest way to do something, such as pressing a keyboard shortcut or clicking a menu item (instead of trying to position the cursor at an offset on the screen and clicking).
Activate the application first. Note that you should never treat these methods as blocking. You may want to add delay()
in some cases.
it = Application('iTunes');
it.activate();
You need to get the application via the System Events processes
property. You can use the byName()
on that collection for convenience.
var its = se.processes.byName('iTunes');
Next, if security settings are set, we should be able to get the menu. Most applications will only have one menuBar
however some applications will have more than one, such as a "tray icon". So while in AppleScript you would use menu bar 1
, here you iterate from 0.
All menu bars contiain a menuBarItems
property, which also has a byName()
convenience method.
In menuBarItems
you would find Apple
(which is the Apple menu), an item with the name of the application, and the other menus after (if there are any).
var fileMenu = proc.menuBars[0].menuBarItems.byName('File');
We can .click()
this one but it will be so fast we probably will not see anything.
The structure of a menu contains further with menuBarItem
objects containing a menus
property. This may seem confusing as the name of it will refer to itself, but this is the actual equivalent to NSMenu
in AppleScript. It will have the items we are looking for. Usually the first item is all we need.
var editMenu = proc.menuBars[0].menuBarItems.byName('Edit');
editMenu.menus[0].menuItems.byName('Select All');
The structure of .menuItems.byName()
to .menus[0]
to .menuItems.byName()
will continue as the menu has more children. If the name is dynamic, simply grab the menu items and use something like a regular expression:
items = fileMenu.menus[0].menuItems(); // Note ()
for (var item, i = 0, j = items.length; i < j; i++) {
item = items[i];
if (item.enabled() &&
/^Log out myname/.test(item.title()) { // again note () on attributes
item.click();
}
}
The major disadvantage to name matching is locale. Nothing here is locale-aware. If you need to support multiple languages, you may want to research into bridging with $.NSLocalizedStringFromTableInBundle()
or the NSLocale
API.
- Foreword
- Conventions Used in This Cookbook
- Using JavaScript for Automation
- ES6 Features in JXA
- Getting the Application Instance
- User Interactions
- User Interaction with Files and Folders
- Using Objective-C (ObjC) with JXA
- Shell and CLI Interactions
- Importing Scripts
- iTunes
- Keynote
- Messages
- System Events
- Safari & Chrome
- Script Editor
- XML
- Examples