Apple script find and replace text - applescript

So, right now my code clicks on a textarea in safari then it adds a word using keystroke, however I was wondering if there is a way to find and replace a word in that area and also is there a way to replace a highlighted word without keystroke?
Current code:
Sorry its very very poorly formatted since I am pretty bad at applescript
to clickClassName(theClassName, elementnum)
tell application "Safari"
do JavaScript "document.getElementsByClassName('" & theClassName & "')[" & elementnum & "].click();" in document 1
end tell
end clickClassName
to clickID(theId)
tell application "Safari"
do JavaScript "document.getElementById('" & theId & "').click();" in document 1
end tell
end clickID -- All the code up to this point did is allow me to click on IDs and classes in safari.
tell application "Safari" to activate
tell application "System Events"
tell application "Safari"
tell window 1
set current tab to (make new tab with properties {URL:"https://en.wikipedia.org/w/index.php? title=User:USERNAMEHERE/sandbox&action=edit"})
end tell
end tell
end tell
delay 2 -- All the code up to this point from the last comment did is open a new tab in safari.
repeat 5 times
set randomlist to {"1","2","3","4"} -- List of numbers that will be randomly selected and put in the texarea
set randomword to some item of randomlist
clickClassName("tool-button wikiEditor-toolbar-spritedButton", 0) -- This clicks the bold button on the sandbox page
tell application "System Events"
tell process "Safari"
keystroke randomword -- Uses keystroke to put replace the text inside the bold formatting area
end tell
end tell
delay 1
clickID("wpSave") -- Clicks save
delay 2
tell application "Safari" to set the URL of the front document to "https://en.wikipedia.org/w/index.php? title=User:USERNAMEHERE/sandbox&action=edit" -- Goes back to sandbox and repeats the process
delay 2
end repeat
If you want to test this then put in your wikipedia username in the link and login into your account. Pretty much its a wikipedia bot that will just put stuff in my wikipedia sandbox

Related

AppleScript does not run from calendar

I made the following code to open a website, insert some required text, click "View", and download the resulting document. It runs perfectly if I manually click on it. It also works if I schedule a calendar event to call it when I am sitting in front of my Mac. I have tried every combination of keeping the display on/off and screen unlocked/locked. For some reason, it doesn't seem to work at 5:30am and 2:00pm when I set it to run. I have checked to make sure the disk and Mac are not going to sleep as well. Any thoughts on what I am doing wrong would be greatly appreciated.
--Quit Safari before the program starts
tell application "Safari"
close every window
end tell
--empty "Downloads" folder
tell application "System Events"
delete (every file of folder ("/Users/97pubs/Downloads"))
end tell
--opens DINS website
tell application "Safari"
make new document with properties {URL:"https://www.notams.faa.gov/dinsQueryWeb/"}
activate
ignoring white space
tell front document to repeat until its text contains "About DINS"
end repeat
end ignoring
log "Finished loading"
end tell
delay 2
--Function to press DoD banner on DINS website
to clickClassName(theClassName, elementnum)
tell application "Safari"
do JavaScript "document.getElementsByClassName('" & theClassName & "')[" & elementnum & "].click();" in document 1
end tell
end clickClassName
clickClassName("ui-state-default", 0)
delay 2
--Function to input ICAO abbreviations on the page
to inputByName(theName, num, theValue)
tell application "Safari"
do JavaScript "
document.getElementsByName('" & theName & "')[" & num & "].value ='" & theValue & "';" in document 1
end tell
end inputByName
inputByName("retrieveLocId", 0, "kmaf")
delay 2
--Function to click "View NOTAMs" on page
to clickName(theName, elementnum)
tell application "Safari"
do JavaScript "document.getElementsByName('" & theName & "')[" & elementnum & "].click();" in document 1
end tell
end clickName
--Clicks "View NOTAMs" on page
clickName("submit", 0)
--Waits for next window to completely load before continuing
tell current application
tell application "Safari"
tell window 1
repeat until (exists tab 2)
delay 1
end repeat
ignoring white space
tell front tab to repeat until its text contains "DINS Disclaimer"
end repeat
end ignoring
end tell
end tell
end tell
delay 1
--Clicks "Save all NOTAMs" on page
clickName("button", 1)
delay 2
--Waits for download to complete before continuing
set someFolder to "/Users/path/to/save/location/" -- put your download folder path here
if not (waitForFilesToCopy into someFolder for (10 * minutes)) then
display alert "Error with downloads" message "The downloads did not complete in the time allowed."
if button returned of the result is "Cancel" then error -128
end if
to waitForFilesToCopy into theFolder for timeToWait
(*
waits up to the timeToWait for files to be copied/downloaded to theFolder the test is based on the size of the folder not changing after several seconds the rough timeToWait may need to be adjusted if copying several files/folders parameters - theFolder [mixed]: the folder to check timeToWait [integer]: a maximum timeout value in seconds returns [boolean]: true if copy/download finished, false if timeout
*)
set {theFolder, possible, interval} to {theFolder as text, false, 2} -- change the check interval as desired
tell application "System Events" to set currentSize to size of disk item theFolder -- get initial size
repeat (timeToWait div interval) times -- check every interval seconds
delay interval
tell application "System Events" to set newSize to size of disk item theFolder -- recheck size
if (newSize is equal to currentSize) then
if possible then -- no change since last time
return true -- success
else -- one more time...
set possible to true
end if
else -- update size & possible switch
set {currentSize, possible} to {newSize, false}
end if
end repeat
return false -- fail (timeout)
end waitForFilesToCopy
--Rename PDF to "5 Local NOTAMs.pdf"
tell application "System Events" to set name of file "/Users/path/to/save/location/temp.pdf" to "5 Local NOTAMs.pdf"
--Move NOTAMs to "CrewPapers" folder
tell application "Finder"
move POSIX file "/Users/path/to/save/location/5 Local NOTAMs.pdf" to POSIX file "/Users/path/to/new/location" with replacing
end tell
--Close Safari and Preview windows
tell application "Safari"
close every window
end tell
tell application "Preview"
close every window
end tell

How to click button in AppleScript?

Writing an AppleScript to open Image Capture and click the Import All button.
tell application "Image Capture"
activate
tell application "System Events"
tell process "Image Capture"
click button "Import All" of group 1 of splitter group 1 of window 1
end tell
end tell
end tell
Image Capture opens but the script throws an error message saying it couldn't find the button "Import All".
Have followed advice on other threads on how to check the location in Accessibility Inspector and how to translate that to AppleScript instructions.
What's missing?
To get the button and group numbers, you have 2 ways: use the utility aplication provided by Apple in the developper toolkit "Accessibility Inspector" or use small scripts to find the number yourselves.
I prefer using script method. it is a bit longer sometime, but it always works. Just write a script with instruction get UI elements. Here is a small example of such script:
-- return lis of UI elements of active application and paste result in Excel
property tab : ASCII character 9
global T
-- to find last active application
tell application "System Events"
set frontmostProcess to first process where it is frontmost
set visible of frontmostProcess to false
repeat while (frontmostProcess is frontmost)
delay 0.2
end repeat
set secondFrontmost to name of first process where it is frontmost
set frontmost of frontmostProcess to true
end tell
set ActifProcess to secondFrontmost as text
tell application ActifProcess to activate -- set active the last actived application
delay 1
-- recursive loop to list all elements of active window
tell application "System Events" to tell process ActifProcess to set myWindow to front window
set T to ""
getUI(myWindow, 1)
set the clipboard to T
display dialog "Result is in clipboard. paste in Excel or text document"
on getUI(UIObjet, myLevel) -- get recursively the list of UI elements
set AppleScript's text item delimiters to {"//"}
tell application "System Events" to set UIliste to UI elements of UIObjet
repeat with oneUI in UIliste
tell application "System Events"
set UItext to ("Level=" & myLevel & tab & "Name=" & (name of oneUI) & tab & (description of oneUI) & tab & "Class=" & (class of oneUI) as string) & tab & "Title=" & (title of oneUI) as string
set UItext to (UItext & tab & "Value=" & (value of oneUI) as string) & tab
try
set UItext to (UItext & "Position=" & (position of oneUI) as text)
end try
set UItext to UItext & return
try
set NbSub to count of UI elements of oneUI
on error
set NbSub to 0
end try
set T to T & return & UItext
end tell
if NbSub > 0 then
getUI(oneUI, myLevel + 1) -- there are other sub UI elements, get them
end if
end repeat
end getUI
Copy this script in Script Editor. Make active the window/application you want to get UI elements. Make this script active and run.
The result is sometime not easy to interpret because developper of the application/window you're looking for may not have use UI element clear names or titles which describe what they are. Then you will have to look their relative position in the window.
The "import all" button is "button 3 of group 2 of splitter group 1 of window 1" for image capture version 6.6. Also, I prefer to use button number, instead of button name to make sure the script works with any language.
tell application "Image Capture"
activate
tell application "System Events"
tell process "Image Capture"
click button 3 of group 2 of group 1 of splitter group 1 of window 1
end tell
end tell
end tell
Please note that any next changes done by Apple on Image Capture will impact your script.

How to wait for webpage to fully load before proceeding script?

How do you wait for a webpage to fully load before proceeding the script?
I know you can use delay 4 if you would want it to wait 4 seconds but this is not safe enough.
In VBA you have a simple code that always works and it goes like this:
Dim x As String
x = "https://na6.salesforce.com/p/attach/NoteAttach?pid=" & Range("T34").Value & "&parentname=" & Range("T35").Value & "&retURL=%2F0018000000sKz8K%3Fpb0%3Dtrue"
Set IE = CreateObject("InternetExplorer.Application")
IE.Navigate (x)
IE.Visible = True
SetParent IE.Hwnd, Application.Hwnd
Do
DoEvents
Loop Until IE.READYSTATE = 4
What would be the equivalent of this on mac with safari for applescript?
I´ve seen many versions on the net but only workarounds similar to the delay or for a specify value to return or to count words on the page and so on.
I simply want the above version which is 100% perfect.
Thank you in advance:)
You can access the ready state of a page by calling "document.readyState" from either Safari or Chrome.
tell application "Safari"
if not (exists document 1) then reopen
tell current tab of window 1 to set URL to "https://stackoverflow.com/questions/24500011/how-to-wait-for-webpage-to-fully-load-before-proceeding-script"
set the_state to missing value
repeat until the_state is "complete"
set the_state to (do JavaScript "document.readyState" in document 1)
log "busy"
delay 0.2
end repeat
log "complete"
end tell
I do it in this way:
tell document 1 of application "Safari"
set URL to ""
set URL to "/slowly loading page/"
repeat until name is not "about:blank"
end repeat
end tell
Or, even easier:
tell front document of application "Safari"
set URL to "/slowly loading page/"
repeat until length of (source as text) is not 0
end repeat
end tell
Furthermore, there’s no need to do it without any delay:
repeat until length of (source as text) is not 0
delay 0.5
end repeat
Googled a bit and found this code that works for Safari Version 5.1.10 (6534.59.10) on Snow Leopard.
From http://macscripter.net/viewtopic.php?id=35176
tell application "Safari"
activate
repeat until SafariWindowHasLoaded(1) of me is true
end repeat
beep
end tell
on SafariWindowHasLoaded(inWindowIndex)
tell application "System Events" to ¬
tell application process "Safari"
set theStatusText to name of static text 1 of group 1 of window inWindowIndex as text
if theStatusText begins with "Contacting" or ¬
theStatusText begins with "Loading" or ¬
theStatusText begins with "Waiting" then
set theReturnValue to false
else
set theReturnValue to true
end if
end tell
return theReturnValue
end SafariWindowHasLoaded
Only problem I had was that this script was for an older version of Safari and the Status Bar element was in a different group than mine.
At http://hints.macworld.com/article.php?story=20071015132722688 it was suggested to change it to
static text 1 of group 2
and it worked!
I find getting the JavaScript "document.readyState" value the best way to determine if a page has finished loading, but that requires Safari to Developer > Allow JavaScript from Apple Events. Since that's is a security risk, I adjust Safari's preferences to enable it when it's needed, then disable it.
tell application "Safari" to open location ¬
"https://neeva.com/search?q=demon%20cats&c=Image&src=typedquery" -- random site
Wait_For_Safari()
--Feed cats and do other worthy things.
on Wait_For_Safari()
tell application "System Events" to set originatingApp to ¬
name of first application process where frontmost is true --in case we aren't executing from Safari
Allow_Apple_Events() --enable AllowJavaScriptFromAppleEvents so we can get JS's "document.readyState"
tell application "Safari"
set readyState to missing value
repeat until readyState is "complete" --wait for readyState = complete
set readyState to (do JavaScript "document.readyState" in document 1)
delay 0.2
end repeat
delay 0.2
end tell
Disallow_Apple_Events() --Disable AllowJavaScriptFromAppleEvents so our pants aren't down
tell application originatingApp to activate --return to wherever we started
end Wait_For_Safari
on Allow_Apple_Events()
do shell script "/usr/bin/defaults write com.apple.Safari AllowJavaScriptFromAppleEvents 1" --1 = enabled
end Allow_Apple_Events
on Disallow_Apple_Events()
do shell script "/usr/bin/defaults write com.apple.Safari AllowJavaScriptFromAppleEvents 0" --0 = disabled
end Disallow_Apple_Events

Need advice pertaining to applescript automation

I'm trying to write a program that does the following...
Reads a line of text from textedit that contains only a series of URLs (each on a seperate line).
Goes to that URL in the current page on my web browser.
Makes two page clicks on the same location of the loaded page.
Hits the "Enter" button
Repeats from the first step
I am a beginner at applescript... but can learn anything needed to complete this project. Could someone show me an example of the code that I am trying to write?
set urls to "http://stackoverflow.com/questions/18069198
http://stackoverflow.com"
--set urls to read "/tmp/input.txt" as «class utf8»
repeat with u in paragraphs of urls
tell application "Safari"
activate
open location u
delay 1
tell document 1
repeat while do JavaScript "document.readyState" is not "complete"
delay 0.1
end repeat
do JavaScript "document.querySelectorAll('#hlogo a')[0].click()"
end tell
end tell
tell application "System Events" to keystroke return
end repeat

How to open a new window and multiple urls in Safari with apple script?

How do you open a new window in safari and then open multiple tabs with different urls in that window using apple script?
The way to create a new window in Safari is to use the make new document command:
make new document at end of documents with properties {URL:the_url}
This will create a new window with a single tab pointing to the_url and make that window frontmost. Note that make new window at end of windows doesn't work, and just errors out with "AppleEvent handler fails".
Similarly, to create a new tab within a window w, you can use make new tab:
make new tab at end of tabs of w with properties {URL:the_url}
This will create a new tab in window w at the end of the list of tabs; this tab will be pointing to the_url, and it won't be the current tab. Instead of explicitly saying tabs of w, you can also use a tell w block:
tell w
make new tab at end of tabs with properties {URL:the_url}
end tell
That way, tabs implicitly refers to tabs of w.
Putting this all together, we get the following script. Given a list of URLs in the_urls, it will open all of them in a new window; if the_urls is empty, it opens a window with a blank tab.
property the_urls : {¬
"http://stackoverflow.com", ¬
"http://tex.stackexchange.com", ¬
"http://apple.stackexchange.com"}
tell application "Safari"
if the_urls = {} then
-- If you don't want to open a new window for an empty list, replace the
-- following line with just "return"
set {first_url, rest_urls} to {"", {}}
else
-- `item 1 of ...` gets the first item of a list, `rest of ...` gets
-- everything after the first item of a list. We treat the two
-- differently because the first item must be placed in a new window, but
-- everything else must be placed in a new tab.
set {first_url, rest_urls} to {item 1 of the_urls, rest of the_urls}
end if
make new document at end of documents with properties {URL:first_url}
tell window 1
repeat with the_url in rest_urls
make new tab at end of tabs with properties {URL:the_url}
end repeat
end tell
end tell
tell application "Safari"
activate
set the URL of document 1 to "http://www.XXXXXXX.com"
my new_tab()
set the URL of document 1 to "http://www.XXXXXX.com"
end tell
on new_tab()
tell application "Safari" to activate
tell application "System Events"
tell process "Safari"
«event prcsclic» «class menI» "New Tab" of «class menE» "File" of «class mbar» 1
end tell
end tell
end new_tab
Replace the X's with whatever sites you want and keep repeating the code (my new_tab() and set the URL... lines) for each page you'd like to have open.
Referring to this page.
Correct me if this isn't what you were talking about.
Base on Pugmatt's answer I got the following to work...
on run {input, parameters}
tell application "Safari"
activate
make new document with properties {URL:"http://www.apple.com"}
my new_tab()
set the URL of document 1 to "http://www.example.com"
end tell
end run
on new_tab()
tell application "Safari" to activate
tell application "System Events"
tell process "Safari"
«event prcsclic» «class menI» "New Tab" of «class menE» "File" of «class mbar» 1
end tell
end tell
end new_tab
I'm not sure if this is the most efficient way of you this.

Resources