How do I scroll to the top of a window using applescript? - applescript

I want applescript to scroll a window all the way up.
I've tried the page up key, the home key, and I've tried looking for a way to scroll using the built in scrolling capabilities of the window, but I've so far been unable to even move the scrolled position at all.

Basically, use a tell app "System Events" statement to send keystrokes and key codes.
In theory, you could use the following:
keystroke page up key
keystroke page down key
keystroke home key
But for me this doesn´t work. The good news is that you can use the key codes instead. I suggest using the excellent free Full Key Codes application to read them, though it is a bit tricky to let it read two keys pressed simultaneously.
The key codes for the fn+ arrow keys-combos are as following:
Page up: fn+ up key: key code 116
Page down: fn+ down key: key code 121
Home: fn+ left key: key code 115
End: fn+ right key: key code 119
So for example if you had a long page open in Safari, and you want to scroll to its end, use
tell application "System Events"
tell application "Safari" to activate
— to see the animation, we wait a moment:
delay 0.5
key code 119
end tell

With browsers you could also use JavaScript:
tell application "Safari" to tell document 1
do JavaScript "window.scroll(0,0)"
end tell
tell application "Google Chrome" to tell active tab of window 1
execute javascript "window.scroll(0,0)"
end tell

The alternative to sending keystrokes is to use GUI scripting.
Caveat: While GUI scripting is more robust than sending keystrokes for a given version of an application, changes in the application's layout in future versions can break your code.
Also:
GUI scripting requires that access for assistive devices be enabled; enabling requires admin privileges:
up to 10.8, this could be done programmatically, system-wide by executing tell application "System Events" to set UI elements enabled to true (required admin privileges)
Sadly, on 10.9+, this no longer works, and apps must be authorized manually, individually - the system will prompt you on first run (requires admin privileges)
however, in both scenarios tell application "System Events" to get UI elements enabled will report whether access is enabled or not.
Determining the right UI element targets can be non-trivial and tedious; using the Accessibility Inspector utility that comes with Xcode helps. The class names reported by this utility correspond to the UI element classes contained in the System Events dictionary; e.g., AXSplitGroup corresponds to splitter group.
The following scrolls Safari 6.0.3's front window to the top (access for assistive devices must be enabled):
tell application "System Events"
# Use Accessibility Inspector to find the desired target.
tell front window of process "Safari"
tell scroll bar 1 of scroll area 1 of group 1 of group 1 of last group
set value of attribute "AXValue" to 0 # Scroll to top.
end tell
end tell
end tell
Update: As a reminder that this type of scripting works well for a given version of an application, the code had to be changed for Safari 8.0.4:
tell application "System Events"
# Use Accessibility Inspector to find the desired target.
tell front window of process "Safari"
tell scroll bar 1 of scroll area 1 of group 1 of group 1 of group 2
set value of attribute "AXValue" to 0 # Scroll to top.
end tell
end tell
end tell

Related

AppleScript: Toggle Between Safari Windows?

If I have two safari windows open, just one tab in each, how do I get applescript to switch to either of the windows at will? Or in other words, toggle between them.
I tried, activate window 1 (or, the first window), and activate window 2 (or the second window), only ever activates the first window.
I tried open window 1 etc, open doesn't exist.
I tried using the system events, click menu bar 1 option, thinking maybe menu bar 2 was for window 2, didn't work.
I tried making do javascript on a specific tab show that page, couldn't get that to work.
Ultimately I did figure out I could use a keyboard shortcut, but I wanted to see if there was a more 'vanilla' applescript way.
If the windows are not full screen (in different spaces) just change the index of the window
tell application "Safari"
set index of window 2 to 1
end tell
If the windows are in different spaces you have to switch the spaces by executing the keystrokes with System Events. The default values on the US keyboard are ⌃←
tell application "System Events"
key code 123 using (control down)
end tell
and ⌃→
tell application "System Events"
key code 124 using (control down)
end tell
When I do just this
tell application "Safari"
set index of window 2 to 1
end tell
The new window that shows up is frozen. I fixed this by doing this
tell application "Safari"
set theWindows to windows
set win2 to item 2 of theWindows
tell win2
set visible to false
set visible to true
set index to 1
end tell
activate
end tell

How can AppleScript be used to send key codes (or an equivalent) directly to an application?

For instance, while the following is able to send multiple keys (shift+h) to the application "System Events", the script won't compile when attempting to send those key codes to an application such as Google Chrome. Is there another way?
tell application "System Events" (* won't work with "Google Chrome" *)
key code 58
key code 4
end tell
You can send key codes via System Events to an application like this:
tell application "System Events"
tell process "Google Chrome"
set frontmost to true
key code 4
key code 14
key code 37
key code 35
end tell
end tell
You can try this by opening Google Chrome first and making sure the focus is on the (empty) URL field and then run the above script - it should type "help" into the URL field.
If you don’t want Chrome to remain in front you can hide it again after sending the key codes.
As "commented", key codes & keystrokes can NOT be sent to BG apps by AppleScript!
It is ONLY possible to trigger some other ("visible"!) UI elements while in background.
To this purpose you must°° can "select" an application without bringing it to front by:
do shell script "open -g /System/Library/PreferencePanes/Keyboard.prefPane/"
… which works even if the app is already "open" in background.
°°I was reminded though: AS can reveal Sys.Prefs in background, other apps can not.
A 2nd alternative in AS is launch which with some(!) apps will work like "open -g …".
As CJK mentions any next command can be sent via AppleScript:
tell application "System Events" to tell process "System Preferences" ¬
to click checkbox 1 of tab group 1 of window 1
I use this feature to toggle some Sys-Prefs settings without losing focus. *
Remember: ONLY commands for "visible elements" (checkboxes, buttons …) will be executed; menu items therefore are excluded (= not visible while in background).
* ["At home" I use these lines in a Karabiner-shortcut where AS need an osascript wrapping.]

AppleScript to block Safari pop-up windows

I am trying to automate the blocking of pop-up windows in Safari.
I have tried the following defaults write operation
defaults write com.apple.Safari WebKit2JavaScriptCanOpenWindowsAutomatically -boolean false
But this fails to do it. I have also tried setting it as true but even that didn't help. I am currently trying to find a way to do it using AppleScript.
This is what I have written so far -
CMD_ACTIVATE='tell application "Safari" to activate'
CMD_NEWTAB='tell application "System Events" to keystroke "," using {command down}'
osascript -e "$CMD_ACTIVATE" -e "$CMD_NEWTAB"
This opens up the preferences but then I draw a blank. Anyone with any suggestions on how to proceed? Also I don't really need a solution to this only in AppleScript any other way to do it would also be helpful.
Note: I have been using Mac OS only for a week now, and am not that well versed in the nuances of this OS, so please be a bit descriptive when answering.
Thanks.
Blocking pop-up window is done via Safari / preferences / tab Security where you need to set the correct checkbox.
This preference seems to be stored in your library / preferences file com.safari.plist which contains the flag com.apple.Safari.ContentPageGroupIdentifier.WebKit2JavaScriptCanOpenWindowsAutomatically with value Yes when pop-up are blocked.
However, it may not be the only place to be changed and in any cases, it is not officially documented, so that place can be changed by Apple any time. This is not recommended to use it.
Going back to Applescript, because Safari is quite poor in terms of applescript handling events, you are forced to go via GUI scripting. That’s what you’ve started, but keep in mind that if Apple changes the layout of Safari preference window, your script must be reviewed.
When going through GUI scripting (which, again, should only be when no other solution found) you must understand structure of GUI objects. Window contains button, check box, tool bar... in a hierarchy model. For instance the preference window in Safari contains bellow the tool bar, an object "group 1" with itself contains many objects depending of the tool bar current selection. Once you understand that concept, the script below, which does what you're looking for, will be easy to understand with many comments:
tell application "Safari" to activate
tell application "System Events"
keystroke "," using {command down}
delay 0.2 -- leave sometime to open window
tell window 1 of process "Safari"
click button 6 of toolbar 1 -- Security button is number 6
delay 0.2
-- check if check box not yet set and set it.
if (value of checkbox 5 of group 1 of group 1) = 0 then click checkbox 5 of group 1 of group 1
end tell
delay 0.2
click button 1 of window 1 of process "Safari" -- click on red / close button
end tell
I am running on Safari 10.0.3. If your version is different, the preference window may be different. Then the script must be adjusted: the Security tab button may not longer be the number 6 in your version,...

Apple Script Error: Can't continue click

I'm trying to open a messaging application (it does not have an Apple Script Dictionary (command + shift + o)), click on text, and type into the text box, and hit send.
Pop up: Script Error - Telegram got an error: Can't continue click after the application becomes active.
Result Tab: error "Telegram got an error: Can’t continue click." number -1708
P.S., The messaging application is Telegram.
Apple Script:
tell application "Telegram"
activate
delay 1
click on text "chat name"
keystroke "some text"
//assuming this works because text box is the first responder when the chat opens.
click on text "Send"
end tell
If an application lacks an AppleScript dictionary, any command except the standard commands launch, activate, open, reopen and quit will throw an error.
The solution is GUI scripting: The built-in application System Events is the bridge to send mouse clicks and keyboard events to the target application.
I don't know the application Telegram at all, so this code might fail, but it might also be a starting point
activate application "Telegram"
tell application "System Events"
tell process "Telegram"
tell window 1
keystroke "some text"
click button "Send"
end tell
end tell
end tell
You have two choices for a 3rd party app that lacks an AppleScript dictionary.
Option 1:
Use System Events as described above to perform an action on an element, e.g. click a button, keystroke text into a field, etc. The trick is to identify the element in syntax that is recognized by Applescript. Besides UIElementInspector mentioned above, which can be confusing and occasionally wrong/incomplete, you can also run the following commands in a separate Applescript Editor. For example, to get all UI elements for the active window (window 1) in Telegram:
tell application "System Events" to tell application process "Telegram" to tell window 1
UI elements
end tell
To get all UI elements for the main menu bar in Telegram:
tell application "System Events" to tell application process "Telegram" to tell menu bar 1
UI elements
end tell
In each case the Result pane will display a comma delimited list of all available UI elements in that window or menu bar. Moreover, the syntax as listed is guaranteed to be recognizable by Applescript. Just identify the correct element and tell System Events to tell it what to do.
For example if you want to click the Menu item "Format" In TextEdit first run the following:
tell application "System Events" to tell application process "TextEdit" to tell menu bar 1
UI elements
end tell
Among the results in the Result pane will be the following:
menu bar item "Format" of menu bar 1 of application process "TextEdit" of application "System Events"
Convert that to Applescript, run the script and it will click the "Format" Menu:
tell application "TextEdit" to activate --you need TexEdit up and running to click its menu bar
tell application "System Events" to click menu bar item "Format" of menu bar 1 of application process "TextEdit"
For submenus, etc. you just iterate the process asking for UI elements for the submenu. GUI scripting is iterative and empirical.
Option 2:
Download the free Terminal/Command Line app cliclick which allows you to click on any point in the screen. The screen coordinates you want to click can be manually identified with your cursor by holding down command + shift + 4.

How to automate clicking a specific button repeatedly with AppleScript?

I'm trying to write a script that will:
Open a particular program
Click on a button at a particular spot within the program window
Repeat the click a certain number of times with a specified delay between clicks
I'm planning to use iCal to schedule running the script, but what should the actual script look like? Could it be run on the background without making any windows visible?
Most native applications support UI scripting like this:
reopen application "Finder" -- open a default window if there are no open windows
tell application "System Events" to tell process "Finder"
repeat 3 times
click button 2 of window 1
delay 1
end repeat
end tell
If you get an error like "Access for assistive devices is disabled", enable access for assistive devices from the accessibility preference pane.
If you have Xcode, you can use Accessibility Inspector to inspect UI elements. Or use something like this:
reopen application "Finder"
tell application "System Events" to tell process "Finder" to tell window 1
{class, value} of UI elements of UI elements
description of UI elements
properties of some UI element
attributes of some UI element
value of attribute "AXFocused" of some UI element
actions of button 2
end tell
If click doesn't work, try perform action "AXPress", set selected to true, or set focused to true.

Resources