Run Javascript on the specific process id of Safari - macos

I have the script like this here:
on run argv
set pid to item 1 of argv
set fileLocation to item 2 of argv
tell application "System Events"
set theprocs to every process whose unix id is pid
repeat with proc in theprocs
set the frontmost of proc to true
using terms from application "Safari"
set theScript to "document.querySelector(\"input[name='fileField']\").click()"
tell application "Safari" to do JavaScript theScript in current tab of first window
end using terms from
tell proc
keystroke "G" using {command down, shift down}
delay 2
key code 51
delay 2
keystroke fileLocation
delay 10
key code 52
delay 5
key code 52
delay 5
end tell
end repeat
end tell
end run
which is trying to do the file upload process on the Safari browser. The main goal is to run the script against the given process id ( as many Safari will be running on the machine).
I have problem here with the line do JavaScript from:
tell application "Safari" to do JavaScript theScript in current tab of first window
this is executing the click call on the different Safari browser, rather than the one given in the pid.
I just want to make sure that the script runs against the given Safari PID.
How can I do that?

Related

macOS send keystroke to the active app periodically

I am trying to send a keystroke (command+ shift+ r) to a macOS (Mojave) app called "Dbeaver" every minute as long as DBeaver is the active app. I have tried the following with no effect.
tell application "System Events"
set activeApp to name of first application process whose frontmost is true
if "DBeaver" is in activeApp then
tell application "System Events" to keystroke "r" using {command down, shift down}
end if
end tell
The script works perfectly fine if its simple like the following:
activate application "DBeaver"
tell application "System Events" to keystroke "r" using {command down, shift down}
I do not have the application you referred to but I tested this following AppleScript code using TextEdit.app and it worked. Let me know if you run into any errors or issues
tell application "System Events"
repeat while (exists of application process "DBeaver")
set activeApp to name of first application process whose frontmost is true
if "DBeaver" is in activeApp then
tell its application process "DBeaver"
repeat while frontmost
keystroke "r" using {command down, shift down}
delay 60
end repeat
end tell
end if
end repeat
end tell
You want to avoid using something like a repeat loop, as that will block the app's user interface (for quitting or to just avoid the spinning wheel of death). A relatively easy way to repeat stuff like that is to make a stay-open application, and put your repeating code in the idle handler, which uses a timer - for example:
on idle
tell application "System Events"
set activeApp to name of first application process whose frontmost is true
if "DBeaver" is in activeApp then
tell application "System Events" to keystroke "r" using {command down, shift down}
end if
end tell
return 60 -- do it again in 60 seconds
end
The statements in the idle handler are run when the app is idle; the return value determines the number of seconds before the handler is run again.

Get text from current cursor position From Pages app in Mac

Is it possible to get the text of Pages app, from its current cursor position?
My requirement is like, when user type something in "Pages", I have to show suggestions for the word they are typing.
so I want to find out the current or last word, near current cursor position from "Pages" app.
Either by using AppleScript or Accessibility?
Text is not selected.
I am not looking for "Services" also.
For apps other than "Pages", I used Accessibility and appleScript. but for pages I am not finding any way.
I have also tried below AppleScript, but some reason it works perfectly in "Script Editor", but when I use it in my code, it goes to infinite loop.
tell application "Pages"
activate
end tell
tell application "System Events"
tell application "System Events"
key code 123 using {shift down, command down} -- shift-command-left
end tell
tell process "Pages"
keystroke "c" using {command down}
delay 1
tell application "System Events"
key code 124 -- shift-command-left
end tell
set myData to (the clipboard) as text
return myData
end tell
end tell
If I run this AppleScript in my app, it freeze my Mac only, I have to force quit the Mac to stop it.
This works for me using the latest versions of macOS Mojave and Pages
property theApp : "Pages" -- change value to name of any other application (TextEdit)
tell application theApp to activate
delay 3
tell application "System Events"
tell application process theApp
-- Move the insertion point to the beginning of the previous word.
key code 123 using {option down} -- left arrow key while holding option down
delay 0.2
-- Move the insertion point to the end of the next word. (selects the word)
key code 124 using {shift down, option down} -- right arrow key while holding option and shift down
delay 0.2
keystroke "c" using {command down} -- copies selected wprd
delay 0.2
-- Next 2 key code commands attempt to restore cursor location
key code 124 using {option down} -- right arrow key while holding option down
delay 0.2
key code 123 using {option down} -- left arrow key while holding option down
tell current application to set myData to (the clipboard) as text
delay 4
return myData
end tell
end tell

Applescript for auto scrolling in Font Book. I could use some expert guidance

As a graphic designer, I am constantly having to identify which fonts to use in a document or match a font. Currently I have over 5000 different fonts. I don't keep all 5000 installed on my system. However, I usually do have to scroll through custom collections of 1000 fonts or more using the down arrow key. Sometimes the whole process takes me the better part of an hour
I created a script for auto scrolling in Font Book and saved it as an application named “FontBook_Auto_Scroll.app”. Basically it opens a dialog window giving me three options. If I select “arrow down”, it brings Font Book to the front and pushes the arrow down key 35 times in increments of half a second.
Then the dialogue window opens again. If I select “arrow up”, it brings Font Book to the front and pushes the arrow up key 7 times, etc. But here is the problem. If in the process of “scrolling down”, I see the font I want to use and it happens to appear as the second font in the “scrolling down” cycle, I would prefer not to have to wait until the 35 arrow key down entries are completed.
I'm still playing around with this script and making revisions as I continue reading AppleScript help documents. This is what I have so far.
property selectedFontFamily : missing value
tell application "Font Book"
activate
delay 5
try
set (selected collections) to font domain "AllFonts"
on error errMsg number errNum
set (selected collections) to font domain "AllFonts"
end try
try
set (selected font families) to font family 1
on error errMsg number errNum
set (selected font families) to font family 1
end try
end tell
tell application "System Events"
repeat 2 times
key code 48
end repeat
end tell
delay 1
repeat 40 times
activate
display dialog "Font Book Scrolling" buttons {"Arrow Down", "Arrow Up", "Cancel"} default button 1 giving up after 7
set the button_pressed to the button returned of the result
if the button_pressed is "" then
tell application "Font Book"
activate
delay 1
set (selected collections) to font domain "AllFonts"
tell application "System Events"
key code 37 using {command down, option down}
end tell
delay 1
set selectedFontFamily to (selected font families)
end tell
tell application "System Events"
delay 3
repeat 55 times
delay 0.6
key code 125
end repeat
delay 1
end tell
tell application "Font Book"
set selectedFontFamily to (selected font families)
tell application "System Events"
key code 37 using {command down, option down}
end tell
end tell
else if the button_pressed is "Arrow Down" then
tell application "Font Book"
activate
set (selected collections) to font domain "AllFonts"
tell application "System Events"
key code 37 using {command down, option down}
end tell
set selectedFontFamily to (selected font families)
end tell
tell application "System Events"
delay 3
repeat 55 times
delay 0.6
key code 125
end repeat
delay 1
end tell
tell application "Font Book"
set selectedFontFamily to (selected font families)
tell application "System Events"
key code 37 using {command down, option down}
end tell
end tell
else if the button_pressed is "Arrow Up" then
tell application "Font Book"
activate
set (selected collections) to font domain "AllFonts"
tell application "System Events"
key code 37 using {command down, option down}
end tell
set selectedFontFamily to (selected font families)
end tell
tell application "System Events"
delay 1
repeat 15 times
delay 0.7
key code 126
end repeat
delay 1
end tell
tell application "Font Book"
set selectedFontFamily to (selected font families)
tell application "System Events"
key code 37 using {command down, option down}
end tell
end tell
else if the button_pressed is "Cancel" then
tell application "Font Book"
quit
end tell
return
end if
end repeat
quit
end
on quit
tell application "Font Book"
quit
end tell
continue quit -- allows the script to quit
end quit
It's been my experience that once an AppleScript application starts running its script, sans coded exit points, the only way to get out of a loop is to force quit the application.
Because one may have more then one AppleScript application running at a time and the executable's name, regardless of what one named the application, is applet, you don't want to use a command like do shell script "kill -9 $(pgrep applet)", as it will kill all running AppleScript applications.
I'd have second AppleScript application handy, e.g. "Terminate - FontBook_Auto_Scroll.app", in the Dock for quick access, to isolate the PID of the target AppleScript application, using the following command syntax:
do shell script "kill -9 $(ps -x | awk '/[N]ame.app/{print $1}'); exit 0"
In the case of your "FontBook_Auto_Scroll.app", the command would be:
do shell script "kill -9 $(ps -x | awk '/[F]ontBook_Auto_Scroll.app/{print $1}'); exit 0"
The first character of the application's name is in square braces so as not to confuse the PID returned of the awk query that has the target AppleScript application's name in it.
The ; exit 0 it there so if you accidentally run the AppleScript application that terminates the target AppleScript application when it's not running, it does not error out.
Then when you want to stop the scrolling, use the "Terminate - FontBook_Auto_Scroll.app" AppleScript application to terminate the "FontBook_Auto_Scroll.app" AppleScript application.
BTW Looking at the coding of your AppleScript application, the issue you're going to run into is while it's in the loop, if you set focus elsewhere, the key code events are going to go to whatever has focus.
Update:
Here is some example code, using cliclick, to programmatically mathematically calculate, based on the properties of the UI Elements, where to click.
Tested under macOS 10.12.5, this code will click the All Fonts collection, then the first Font in that collection.
Note: Change the value of the cliclick variable based on where it's located on your system.
set cliclick to POSIX path of (path to home folder as string) & "bin/cliclick"
tell application "Font Book"
activate
-- delay 1
tell application "System Events"
set position of window 1 of application process "Font Book" to {0, 22}
set size of window 1 of application process "Font Book" to {800, 622}
set theFontBookAllFontsProperties to ¬
get properties ¬
of static text 1 ¬
of UI element 1 ¬
of row 2 ¬
of outline 1 ¬
of scroll area 1 ¬
of splitter group 1 ¬
of window 1 ¬
of application process "Font Book"
set theFontBookAllFontsPosition to position in theFontBookAllFontsProperties
set theFontBookAllFontsSize to size in theFontBookAllFontsProperties
set theXpos to (item 1 of theFontBookAllFontsPosition) + (item 1 of theFontBookAllFontsSize) / 2 as integer
set theYpos to (item 2 of theFontBookAllFontsPosition) + (item 2 of theFontBookAllFontsSize) / 2 as integer
tell current application
-- delay 0.25
do shell script cliclick & " c:" & theXpos & "," & theYpos
end tell
set theFontBookAllFontsFirstFontsProperties to ¬
get properties ¬
of static text 1 ¬
of UI element 1 ¬
of row 1 ¬
of outline 1 ¬
of scroll area 2 ¬
of splitter group 1 ¬
of window 1 ¬
of application process "Font Book"
set theFontBookAllFontsFirstFontsPosition to position in theFontBookAllFontsFirstFontsProperties
set theFontBookAllFontsFirstFontsSize to size in theFontBookAllFontsFirstFontsProperties
set theXpos to (item 1 of theFontBookAllFontsFirstFontsPosition) + (item 1 of theFontBookAllFontsFirstFontsSize) / 2 as integer
set theYpos to (item 2 of theFontBookAllFontsFirstFontsPosition) + (item 2 of theFontBookAllFontsFirstFontsSize) / 2 as integer
tell current application
-- delay 0.25
do shell script cliclick & " c:" & theXpos & "," & theYpos
end tell
end tell
end tell
Note: The delay commands may or may not be necessary and or may or may not need to have the value of the delay modified. Uncomment and set as appropriate to the needs.

applescript copy paste between textedit and 3rd party application not working

I have searched all over this site and cannot find an answer to why this code isn't doing what I need it to do. I have a textedit doc with a list of numbers. I want to copy 1 number at a time paste that number into a 3rd party application at a specific place in url, and then hit some buttons in the ui of that application. I need this process to repeat for each individual number in the textedit document.
Here is what I came up with after researching applescript.
tell application "TextEdit" to activate
tell application "System Events"
tell process "TextEdit"
key code 124 using {shift down, command down}
keystroke "c" using command down
key code 125
end tell
end tell
delay 1.0
tell application "import.io" to activate
tell application "System Events"
tell process "import.io"
keystroke tab
keystroke tab
key code 124
key code 123
key code 123
key code 123
key code 123
key code 123
key code 123
key code 123
key code 123
key code 123
key code 123
key code 123
key code 123
key code 123
key code 123
key code 51
keystroke "v" using command down
keystroke tab
key code 76
end tell
end tell
-- Make a selection from the popupbutton.
delay 2.231426
set timeoutSeconds to 10.0
set uiScript to "click pop up button 1 of window \"Save\" of application process \"import.io\""
my doWithTimeout(uiScript, timeoutSeconds)
return input
end run
on doWithTimeout(uiScript, timeoutSeconds)
set endDate to (current date) + timeoutSeconds
repeat
try
run script "tell application \"System Events\"
" & uiScript & "
end tell"
exit repeat
on error errorMessage
if ((current date) > endDate) then
error "Can not " & uiScript
end if
end try
end repeat
end doWithTimeout
-- Click the “<fill in title>” checkbox.
delay 1.496275
set timeoutSeconds to 10.0
set uiScript to "click checkbox 1 of window \"Save\" of application process \"import.io\""
my doWithTimeout(uiScript, timeoutSeconds)
return input
-- Type “Data” into the text field.
delay 7.290406
set timeoutSeconds to 10.0
set uiScript to "click text field 1 of group 17 of list 1 of scroll area 1 of scroll area 1 of browser 1 of splitter group 1 of splitter group 1 of group 2 of window \"Save\" of application process \"import.io\""
keystroke "Data"
keystroke "."
tell application "System Events" to tell process "import.io"
keystroke "v" using command down
end tell
my doWithTimeout(uiScript, timeoutSeconds)
return input
-- Click the “Save” button.
delay 1.475013
set timeoutSeconds to 10.0
set uiScript to "click UI Element \"Save\" of window \"Save\" of application process \"import.io\""
my doWithTimeout(uiScript, timeoutSeconds)
return input
my textedit document is formatted like this:
50
100
150
200
etc
When I run the script this is what it does to my textedit document:
50
50
100
150
200
etc
Any idea what is going on here? I can't make heads or tails of it.
Looking for result in your TextEdit file, first you must start to simplify the textEdit copy part. I assumed that the TextEdit document is already open.
The script bellow provides simplification for copy part :
tell application "TextEdit"
activate
set myNumbers to every paragraph of front document
end tell
repeat with aNumber in myNumbers -- loop through each number
set the clipboard to aNumber
-- insert here the paste instructions in your third party application
end repeat
You must insert the instruction about the paste in the loop, after the 'set clipboard...' instruction which fills the clipboard with a number.
I can't help you for the paste part, because I don't know your third party application, however, your program calling other scripts in doWithTimeout routine does not seems to be very clean and efficient.
If this third party application is not scriptable, at least you may have to go via GUI scripting or java (if java based application).
For instance, instead of doing all the key arrows to move to correct input cell, try to address that cell directly by its GUI properties.
Same for the checkbox, you can also use GUI click function.
The disadvantage of GUI scripting is that application interface must not changed. But this is already the case in your script.

Applescript keystroke Filepath variable

I am trying to create a script that will upload products for me using Applescript and Automator. Im getting an error when the script tries to use the variable for the file path as it iterates through my list. The code is below. I am also inputing the contents of a folder from automator into this script. The error is on line 22. Also, if you could help with the second keystroke on line 42 which needs to iterate with the repeat but in a different folder. Thanks in advance!
on run {input, parameters}
repeat with theItem in input
tell application "Safari"
do JavaScript "document.getElementsByClassName('btn-com btn-info btn-large btn-icon-left add-product-button')[0].click();" in document 1
delay 1
do JavaScript "document.getElementsByClassName('btn-com btn-info btn-large btn-icon-left add-product-button')[0].click();" in document 1
delay 1
do JavaScript "document.getElementById('editor_commerce_product_short_description').innerHTML = 'All photos include full rights to the image and arrive via email. Comes in full 4K resolution. Image displayed is 1080P resolution. Orders may take up to 2 hours to be delivered. Watermarks will be removed!';" in document 1
delay 1
do JavaScript "document.getElementById('editor_commerce_product_price').value = '1.99';" in document 1
do JavaScript "document.getElementsByClassName('btn dropdown-toggle selectbox-display')[0].click();" in document 1
do JavaScript "document.getElementsByClassName('selectbox-content')[1].click();" in document 1
do JavaScript "document.getElementsByClassName('w-upload-input')[2].click();" in document 1
end tell
delay 1
tell application "System Events"
keystroke "G" using {command down, shift down}
delay 1
keystroke theItem
delay 1
keystroke return
delay 1
keystroke return
delay 1
end tell
delay 60
tell application "Safari"
do JavaScript "document.getElementsByClassName('w-upload-input')[1].click();" in document 1
end tell
tell application "System Events"
keystroke "G" using {command down, shift down}
delay 1
keystroke "~/Desktop/Test_Samples/Test_1.png"
delay 1
keystroke return
delay 1
keystroke return
delay 1
end tell
tell application "Safari"
do JavaScript "document.getElementsByClassName('save-product btn-com btn-success')[0].click();" in document 1
end tell
end repeat
return input
end run
It depends on the class of input / theItem. Keystrokes must be text, input can be anything.
Try
keystroke (theItem as text)
or
keystroke (POSIX path of theItem)
And in System Events the equivalent of ⇧⌘G is
keystroke "g" using {command down, shift down}

Resources