While there is a nice albeit a bit crude way to add buttons to a Google Sheet, there is unfortunately no such option in Google documents. So how can I automate repetitive tasks that necessitate running Apps Script within a Google Doc (or within Google Sheets, or Slides, or …)?
It was actually not overly complicated even for a complete AppleScript novice who is still on trial by Script Debugger. (I have still a day left in my trial version of Script Debugger and still wondering what is the difference between AppleScript scripts, bundles libraries and apps; but of course 60 years of teaching CS doesn’t hurt…)
The idea is to have a tab in Google Chrome open with the Apps Script of the document and use AppleScript to click either the “Run” or even the “Debug” button. The code below uses MouseTools - thanks @HAMSoft_Hank! - to click at the given location on the screen so the only nuisance was to find out the CSS selectors of the <button>s in Google’s HTML. The 3 lines of JavaScript to find the location of the button where pretty trivial. Then I only needed to adjust it to make it relative to the Chrome window’s position on the screen.
Needless to say it would be pretty easy to adjust the code to Safari’s way to run JavaScript in a document given that the JavaScript part of the code is exactly the same.
Moreover, the script can be easily adapted to clicking on any page element on any web page and for instance insert the text or image from the clipboard there or select a part of the page and copy it into the clipboard (my next task). And so on - I see quite a few interesting possibilities in my projects… (Could I even insert <script> into the page and run it?)
Hope some of you will find it useful…
use AppleScript version "2.4" -- Yosemite (10.10) or later
use scripting additions
global mouseToolsPath
set mouseToolsPath to quoted form of POSIX path of ((path to home folder as text) & "UnixBins:MouseTools")
runAppsScript()
-- Clicks on 'Debug' button in Google App Script page to debug the currently selected function
on debugAppsScript()
clickOnAppsScriptElement("button[aria-label=\"Debug the selected function\"]")
end debugAppsScript
-- Clicks on 'Run' button in Google App Script page to execute the currently selected function
on runAppsScript()
clickOnAppsScriptElement("button[aria-label=\"Run the selected function\"]")
end runAppsScript
-- Clicks on HTML element in Google App Script page identified by 'cssSelector'
on clickOnAppsScriptElement(cssSelector)
local elementCenterJS, x, y, x1, y1, x2, y2, dy -- to show the values in Script Debugger
-- JavaScript code that returns center of HTML element identified by 'cssSelector'
set elementCenterJS to ¬
"var area = document.querySelector('" & cssSelector & "').getBoundingClientRect();" & return & ¬
"[Math.round(area.x + area.width / 2), Math.round(area.y + area.height / 2)];"
set dy to 78 -- height of Chrome's bars (tab bar and URL/address bar)
tell application "Google Chrome"
activate
delay 1 -- this may need to be adjusted; repeat testing whether Chrome is ready?
set {x1, y1} to execute of front window's active tab javascript elementCenterJS
set {x2, y2} to front window's bounds
set {x, y} to {x1 + x2, y1 + y2 + dy}
end tell
my niceMoveTo(x, y) -- leave this out if you don't like movies
my clickAt(x, y)
delay 5 -- just for the movie to enjoy the effect
end clickOnAppsScriptElement
-- Clicks at point (x,y) on screen
on clickAt(x, y)
mouseToolsAt(x, y, "leftClick")
end clickAt
-- Double-clicks at point (x,y) on screen
on doubleclickAt(x, y)
mouseToolsAt(x, y, "doubleLeftClick")
end doubleclickAt
-- Moves cursor graciously from current location to point(x,y) on the screen
on niceMoveTo(x, y)
local x2, y2, steps
-- cursor's current location
set {x2, y2} to paragraphs of mouseTools("location")
-- 'steps' as length of the line segment from current to target location
set steps to round ((x - x2) ^ 2 + (y - y2) ^ 2) ^ 0.5
-- move nicely (with the same velocity independent of cursor locations)
mouseToolsAt(x, y, "mouseSteps " & steps)
end niceMoveTo
-- Runs MouseTools with 'x', 'y' point on screen and 'suffix' command
on mouseToolsAt(x, y, suffix)
mouseTools("x " & (x as text) & " -y " & (y as text) & " -" & suffix)
end mouseToolsAt
-- Runs MouseTools with just 'suffix' command
on mouseTools(suffix)
return do shell script mouseToolsPath & " -" & suffix
end mouseTools
PS: If you like movies then you may enjoy the recording of the above AppleScript in action.
PSS: I’m sure that you experts will find a lot of improvements - please comment!
PSSS: I am voice typing and when I dictated “debugger” I got “day bugger”! Hmmm, Apple’s AI is on the spot given that it took me more than one day to learn how to use AppleScript - nevertheless they could be a bit less condescending…
PSSSS: I really enjoy Script Debugger, really great job Mark @alldritt!
PSSSSS: Maybe a script that goes through the elements on a page to find the one you clicked and gives you the nicest unique CSS selector so that you don’t need to mess with Google’s messy HTML - Hmmm, how arrogant! (Well, "aria-label"s are nice and, after all, probably fairly common and unique so it can’t be overly difficult in most cases…)