Simple GUI scripting question - user-interface

I am trying this simple GUI script to open a new window of Safari:
tell application "Safari"
activate
end tell
tell application "System Events"
tell process "Safari"
try
tell menu bar 1
tell menu bar item 3
click menu item 1
end tell
end tell
on error theError
display dialog ("An error occurred while performing requested action" & theError) buttons "OK" default button "OK"
end try
end tell
end tell
but it is giving this error message:
Expected end of line but found """
Can anyone suggest me where I may be wrong?
Thanks,
Miraaj

Wow, that was weird. Your script broke AppleScript Editor. After running your script and it not working... I tried to recompile the script and then the error you posted starting showing up. So somehow your code caused AppleScript editor to break and thus the error. I had to quit and relaunch AppleScript Editor to get it working again.
I used the application UI Browser and found the problem. Your reference to the menu item was wrong. There's an extra menu in there that we can't see... and you didn't reference that extra menu. This is the problem with gui scripting. And even if a gui script works it may break at some future date as an application is updated. As such avoid gui scripting if at all possible.
Anyway, here's what your code should look like...
tell application "Safari"
activate
end tell
tell application "System Events"
tell process "Safari"
try
tell menu bar 1
tell menu bar item 3
click menu item 1 of menu 1
end tell
end tell
on error theError
display dialog ("An error occurred while performing requested action " & theError) buttons "OK" default button "OK"
end try
end tell
end tell
EDIT:
As I mentioned in my comment below, if you can't find a native command from an application's dictionary, the next most reliable method is using keyboard shortcuts. Most menu items have them. For example, if I wanted to open a new tab in a window that menu item has the keyboard shortcut command-t. So we can use that like this. Note there is a native command to open a new tab without using keystrokes, I'm just showing this as an example.
tell application "Safari" to activate
tell application "System Events"
keystroke "t" using command down
end tell
end
Keyboard commands don't usually change between application updates whereas gui commands often do because programmers redesign their interface in updates... and when that happens gui scripting goes haywire. One of the gotcha's with both gui scripting and keystrokes is that sometimes the script goes too fast and these techniques can't keep up with the speed of the program, so they often error. When this happens you need to slow down the script using small delays to allow the interface to keep up with the script.

Related

Need script to click button on website that downloads a file

I am new to this so this is probably a dumb question but....
I am trying to get a download to happen off a website by clicking on a link but I don't think I have my code right for AppleScript.
The script opens the right website, but when I try to get it to download the file I need by clicking "export data" the code below doesnt seem to do anything, and am not sure what I am missing/did wrong. No error code. Just doesnt do anything.
Website Here
to clickId(LeaderBoard1_cmdCSV)
tell application "Safari"
do JavaScript "document.getElementById('" & LeaderBoard1_cmdCSV & "').click();" in document 1
end tell
end clickId
Thanks for the help.
The following example AppleScript code will open a new Safari window to the designated URL, wait for the page to finish loading, then click the Export Data link to download the FanGraphs Leaderboard.csv file.
Note: This was tested on macOS High Sierra, however for macOS Mojave and later there is a note in the waitForPageToFinishLoadingInSafari() handler to modify its code. Don't forget to do it if applicable.
To use JavaScript with AppleScript and Safari the Allow JavaScript from Apple Events on the Safari > Develop menu, which is hidden by default, must be checked. It can be shown by checking [√] Show Develop menu in menu bar in: Safari > Preferences… > Advanced
set theURL to "https://www.fangraphs.com/leaders.aspx?pos=all&stats=bat&lg=all&qual=50&type=c%2c6%2c11%2c12%2c13%2c21%2c23%2c39%2c35%2c34%2c41%2c42%2c43%2c104%2c107%2c110%2c206%2c209%2c211%2c50%2c61&season=2019&month=0&season1=2019&ind=0&team=0&rost=0&age=0&filter=&players=0"
tell application "Safari" to ¬
make new document with properties {URL:theURL}
my waitForPageToFinishLoadingInSafari()
my clickId("LeaderBoard1_cmdCSV")
-- # Handlers:
to clickId(ElementID)
tell application "Safari"
do JavaScript "document.getElementById('" & ElementID & "').click();" in document 1
end tell
end clickId
on waitForPageToFinishLoadingInSafari()
-- # NOTE: For macOS Mojave and later, change 'UI element 1' to 'UI element 2` in the code below.
tell application "System Events"
repeat until (accessibility description of ¬
button 1 of UI element 1 of every group of toolbar 1 of window 1 of ¬
process "Safari" whose name = "Reload this page") contains "Reload this page"
delay 0.5
end repeat
end tell
end waitForPageToFinishLoadingInSafari
Note: The example AppleScript code is just that and does not contain any error handling as may be appropriate. The onus is upon the user to add any error handling as may be appropriate, needed or wanted. Have a look at the try statement and error statement in the AppleScript Language Guide. See also, Working with Errors. Additionally, the use of the delay command may be necessary between events where appropriate, e.g. delay 0.5, with the value of the delay set appropriately.

Applescript - How to tell application to open a specific menu item

This is my first attempt to create an applescript.
What i'd like to do is create an apple script and then assing a custom shortcut to it so that it is launched when i need it.
I need it to quickly expand Thunderbird's insert -> HTML... menu.
My current applescript is nested into an automator workflow, and the code is the following:
on run {input, parameters}
tell application "Thunderbird"
activate
tell application "System Events"
tell process "Thunderbird"
click menu item 6 of menu 1 of menu bar item "Insert" of menu bar 1
end tell
end tell
end tell
return input
end run
And when i launch it (after grant permissions to automator), this is the error i get:
Syntax error: System Events got an error; Can't get menu bar item
"Insert" of menu bar 1 of process "Thunderbird"
I think that the proble is because the "Insert" menu is only available when the "Write new message" panel is open in thunderbird...
So my question is, how can i change the script above so that instead of only checking for "Thunderbird" app, it checks that both "thunderbird" and it's own "write new message" panel are open?
And also, is it liklely to be for this reason that i get this error, or i made some mistake in my applescript creation?
Thanks a lot and feel free to ask for more details.

How can I use AppleScript to address dialog box in Ableton Live?

I have a collection of Ableton Live files (extension ".als") that I need to cycle through while playing a show. I'd like to dedicate a keyboard shortcut to launch each one, and had intended to use AppleScript for this.
The issue is that each file gets changed as I go through the process of playing the associated song, so that when I press the keyboard shortcut to launch the .als associated with the next song in my set, Ableton opens the "Save changes before closing?" dialog box (at which point what I want to do is select "Don't Save").
Simply pressing command + D at this point will do the trick, but I'd really like to automate this keypress. I can't seem to figure out how to get applescript to do this. I'm an applescript noob, and clicking the "Open Dictionary" option in AS seems to show that Ableton is not officially a scriptable app.
Any thoughts on this? Here's an example of an AppleScript I've been trying. This starts the process of opening the next .als in my set list, but won't click the "Don't Save" button.
tell application "Finder"
activate
open document file "Song 1.als" of folder "Desktop" of folder "User" of folder "Users" of startup disk
end tell
tell application "System Events"
keystroke "d" using command down
end tell
Interesting!
Finally came across tips that made it work:
Add both the Script Editor and Ableton Live to the Accessibility API:
System Preferences > Security & Privacy > Privacy...
Ignore application responses to continue the script during dialog.
LiveLoader.scpt:
-- open file
ignoring application responses -- don't wait for user input
tell application "Ableton Live 9 Suite" to open "Users:username:Desktop:LiveSet Project:LiveSet.als"
end ignoring
-- use delay if needed
-- delay 0.5
-- skip saving file
tell application "System Events"
set frontmost of process "Live" to true
key code 123 -- left
key code 123 -- left
keystroke return -- enter
end tell
Note:
Consider possible security impact.
Perhaps simply disable apps in Privacy List after use. (Could be scripted ;)
Can now also send mouse clicks, for more creativeness. :)
I know this is old. but in the interest of helping others who might find themselves here... heres what i have done.
use a program call Qlab. the free version will be fine.
make an applescript Cue. go to the 'trigger' tab. select midi trigger. hit the midi key you would like to assign the command too. this cue will now launch when it receives this midi note - even when running in the background.
go to the 'script' tab. copy and paste the script below.
you can make the relevant adjustments for each song. Basically each key will close all current ableton files without saving - as requested. and then launch a specific live set. which ever one you have assigned. in this case, the song 'Less Than Nothing'
the code...
tell application "System Events"
set frontmost of process "Live" to true
keystroke "q" using command down
tell application "System Events" to keystroke (ASCII character 28) --left arrow
tell application "System Events" to keystroke (ASCII character 28) --left arrow
keystroke return
end tell
delay 2.0
do shell script "open '/Users/CamMac/Desktop/Less Than Nothing 2 .als' "

Applescript - Close Pages Document Automatically

I am trying to create a script that will automatically close the frontmost window of Apple Pages.
on run {}
tell application "System Events"
if (window 1 of process "Pages" exists) then
try
tell application "Pages"
--display dialog "Hello World!" --TODO: remove, test code only.
--Keywords I have tried: file, document, window,
close window 1 saving no
end tell
--close window 1 of process "Pages" saving no
on error errMsg
display dialog "ERROR: " & errMsg
end try
end if
end tell
end run
Whenever I run this, it gives me the following error:
ERROR: Pages got an error: window 1 doesn’t understand the “close”
message.
I have looked at this article, and have used the following command:
sudo defaults write /Applications/Pages.app/Contents/Info NSAppleScriptEnabled -bool YES
However, it still fails to work. Any advice?
Details:
System Version: OS X 10.9.1 (13B42)
Kernel Version: Darwin 13.0.0
Pages: 5.0.1
If Pages isn't scriptable, you're kind of out of luck. If it were scriptable, you wouldn't need System Events to close a window; that kind of functionality is usually included in a scriptable app's dictionary.
System Events can help with apps that aren't scriptable, but you have to rely on the actual UI. But if that's the solution, you can't use tell application "Pages" for the inner block (like you have it); you have to use:
tell process "Pages"
If you go that route, now you have to use either the close button on window 1 or use the close menu command. Something like:
activate application "Pages"--note that this will probably be NECESSARY (if it's not frontmost, it prob won't work)
tell application "System Events"
tell process "Pages"
click menu item "Close" of menu "File" of menu bar item "File" of menu bar 1 of it
end tell
end tell
BUT then you have to come up with the problem of what happens if the window hasn't been saved (has been modified) -- which in a scriptable app uses the construction you were originally trying. When using System Events, you can do:
activate application "Pages"--note that this will probably be NECESSARY (if it's not frontmost, it prob won't work)
tell application "System Events"
tell process "Pages"
click menu item "Close" of menu "File" of menu bar item "File" of menu bar 1 of it
delay .5
keystroke "d" using command down
end tell
end tell
But then again how do you make the script smart enough to know if the window has been modified or not? Or maybe you use System Events to see if the window has been killed after the close command, and if it hasn't, it does the keystroke thing. This kind of thing can be done by doing something like:
activate application "Pages"
tell application "System Events"
tell process "Pages"
set frontMostWinName to name of window 1
click menu item "Close" of menu "File" of menu bar item "File" of menu bar 1 of it
tell me to delay 0.5
if exists window 1 then
if name of window 1 = frontMostWinName then keystroke "d" using command down
end if
end tell
end tell
I don't have Pages, but this works with another non-scriptable app, Bean (although I should mention that Bean uses tabs, and I had to move a tab to a window to get this to work*, and I don't know how Pages works in this regard).
[EDIT: *actually, this is not true; this works in Bean regardless of tabs/windows]

AppleScript -> Activate window of a non-scriptable application

I have opened 2 "Finder" window A & B, A is in the front while B underneath, the following snippet brings B to the front the topmost:
tell application "Finder"
activate
activate window 2
end tell
But for applications that do not support scripting, the code just mentioned won't help.
Any ideas for activating a window of non-scripting application.
You can usually turn to system events in these cases. System events knows about the windows of running processes and you can usually manipulate those windows. Something like this will show you some of the things you can do. Just play around with the code and see if you can do what you want.
tell application "System Events"
tell process "Whatever"
properties of windows
end tell
end tell
EDIT: One of the properties of a window is its "title". So you might be able to use that. This approach uses the fact that many applications have a "Window" menu and under that menu many times the name of the windows are listed and you can switch windows by clicking the approprite menu item. So something like this might work... my example uses TextEdit.
tell application "TextEdit" to activate
tell application "System Events"
tell process "TextEdit"
set windowTitle to title of window 2
click menu item windowTitle of menu 1 of menu bar item "Window" of menu bar 1
end tell
end tell
What is your definition of non-scriptable? Just about everything is scriptable to some degree, but for the sake of an example lets use, does not contain an AppleScript dictionary, e.g. AppName.sdef within its application bundle.
For example, the macOS included Stickies application does not contain the Stickies.sdef file, and when trying to add it to the Library in Script Editor is says, "Unable to add the item because it is not scriptable."
In a case such as this, then System Events is needed to talk to the application process, e.g.:
Example AppleScript code:
if running of application "Stickies" then
tell application "System Events"
tell application process "Stickies"
set frontmost to true
if exists window 2 then ¬
perform action "AXRaise" of window 2
end tell
end tell
end if
Notes:
I've included error handling in the example AppleScript code, which can be removed if you prefer.

Resources