I was doing some research on how to invert colors with Applescript. For the most part, I just found stuff like:
tell application "System Events"
keystroke "8" using {command down, option down, control down}
end tell
But on Yosemite (And I think versions before this), this won't work. You have to go into system preferences and click around in there. So, is there a way to make an applescript that would invert colors?(Preferably without having to "Click" anything because that requires accessibility rights for the script)
You can achieve this by using the 'do shell script' command in Applescript, using this:
do shell script "sudo defaults write /Library/Preferences/.GlobalPreferences AppleInterfaceTheme Dark"
That should turn on "dark mode" in OS X Yosemite. Cheers!
In Yosemite JXA Javascript (should be readily adaptable to AS if you prefer)
toggling dark theme and desktop color together:
function run() {
var dctSettings = {
darkMode: {
day: true,
night: false
},
background: {
day: "/Library/Desktop Pictures/Solid Colors/Solid Gray Pro Ultra Dark.png",
night: "/Library/Desktop Pictures/Solid Colors/Solid Gray Light.png"
}
},
strMode;
app = Application("System Events");
if (app.currentDesktop.picture() === dctSettings.background.day) {
app.currentDesktop.picture = dctSettings.background.night;
app.appearancePreferences.darkMode = dctSettings.darkMode.night;
strMode = "Night";
} else {
app.currentDesktop.picture = dctSettings.background.day;
app.appearancePreferences.darkMode = dctSettings.darkMode.day;
strMode = "Day";
}
return strMode;
}
tell application "System Events"
key code 28 using {command down, option down, control down}
end tell
It's 28 and not 8, Key code 28 is for the "8" key on the main part of the keyboard.
Related
noob here trying to teach myself applescript and generally not very smart so apologies :|
i was looking at this question and the answers
Check for active internet connection with Applescript/Automator
and i wanted to make a applescript that runs constantly in the background and that puts a red dot in the menubar when i don't have an internet connection and a green one when i don't (using the AnyBar application) but i can't get it to work properly.
can someone please tell me what i am doing wrong. thank you so much!
repeat
repeat with i from 1 to 2
try
do shell script "ping -o -t 2 www.google.com"
exit repeat
tell application "AnyBar" to set image name to "green"
on error
tell application "AnyBar" to set image name to "orange"
delay 2
if i = 2 then tell application "AnyBar" to set image name to "red"
end try
end repeat
delay 60
end repeat
I'd recommend to use an applet (script saved as application) with an idle handler rather than an infinite repeat loop
property imageName : "red"
property delayValue : 60
property googleURL : "http://www.google.com"
on run
set imageName to "red"
end run
on idle
if (count (get ((googleURL as URL)'s host & {dotted decimal form:""})'s dotted decimal form)) > 0 then
set imageName to "green"
else
if imageName is "green" then
set imageName to "orange"
set delayValue to 2
else if imageName is "orange" then
set imageName to "red"
set delayValue to 60
end if
end if
tell application "AnyBar" to set image name to imageName
return delayValue
end idle
I am working on the same app that I mentioned in my first question. I have gotten much farther, but when I try to play "2048" the first time, AppleScript give me the error:
"The variable result is not defined"
I will skip the main bulky body of the app and get to the area with the problem:
display dialog "What would you like to do?
Sleep = Go to sleep
Finder = Open Finder
Time = Display current time and date
2048 = play 2048
Quit = Quit application" default answer "" with title "Control panel"
if the text returned of the result is "Sleep" then
tell application "System Events" to sleep
display dialog "Hello, welcome back!" buttons {"Thank you!"} default button 1
return
else if the text returned of the result is "Finder" then
tell application "Finder" to make new Finder window
else if the text returned of the result is "Time" then
set a to (current date) as list
set AppleScript's text item delimiters to linefeed
set a to a as text
display dialog a buttons {"OK"} default button 1
else if the text returned of the result is "Quit" then
return
else if the text returned of the result is "2048" then
tell application "Terminal"
do script "/Users/student/Documents/2048.sh"
activate
end tell
else
display dialog "Invalid response" with title "Invalid response" buttons {"Go back", "Quit"} default button 1
end if
if the button returned of the result is "Go back" then
display dialog "What would you like to do?
Sleep = Go to sleep
Finder = Open Finder
Time = Display current time and date
2048 = play 2048
Quit = Quit application" default answer "" with title "Control panel"
else
return
end if
if the text returned of the result is "Sleep" then
tell application "System Events" to sleep
display dialog "Hello, welcome back!" buttons {"Thank you!"} default button 1
return
else if the text returned of the result is "Finder" then
tell application "Finder" to make new Finder window
else if the text returned of the result is "Time" then
set a to (current date) as list
set AppleScript's text item delimiters to linefeed
set a to a as text
display dialog a buttons {"OK"} default button 1
else if the text returned of the result is "Quit" then
return
else if the text returned of the result is "2048" then
tell application "Terminal"
do script "/Users/student/Documents/2048.sh"
activate
end tell
end if
Just set the result of the display dialog to a variable and use the variable. It's tricky to use "result" as you have in many if statements. One of them is bound to cause a problem because "result" will change at some point.
So do something like this right after your display dialog statement...
set {buttonReturned, textReturned} to {button returned of result, text returned of result}
Then in your if statements use buttonReturned or textReturned.
How would I use Applescript to click on a web link in a google search. Can I identify them by name or number or anything?
Safari:
tell application "Safari"
open location "http://google.com/search?q=example"
do JavaScript "window.addEventListener('load', function() {
document.querySelectorAll('.r a')[0].click()
})" in document 1
end tell
Chrome:
tell application "Google Chrome"
open location "http://google.com/search?q=example"
tell active tab of window 1
execute javascript "window.addEventListener('load', function() {
document.querySelectorAll('.r a')[0].click()
})"
end tell
end tell
Edit: try something like this to match a YouTube result by title:
document.querySelector('.yt-uix-tile-link').click()
Edit 2: changed window.onload=function(){} to window.addEventListener('load',function(){}).
Building on #Lauri Ranta's great answer, here is convenience function clickOn(), which:
accepts a target document, a CSS selector string plus a zero-based index to select among what the selector string matches, and simulates a click on the element thus identified.
works irrespective of whether the target document is still being loaded or has already fully loaded - this turned out to be non-trivial. (Lauri's code relies on the window object's load event not to have fired yet).
works with both Safari and Google Chrome (if you don't have Chrome installed, you'll have to comment out a few lines)
Examples that use a delay to demonstrate that the click works even after the document has fully loaded:
# SAFARI
# Click on the *2nd* result returned from googling 'example' with Safari:
tell application "Safari"
open location "http://google.com/search?q=example"
delay 5 # sample delay - NOT needed
my clickOn(document 1, ".r a", 1)
end tell
# CHROME
tell application "Google Chrome"
open location "http://google.com/search?q=example"
delay 5 # sample delay - NOT needed
my clickOn(active tab of window 1, ".r a", 1)
end tell
clickOn source code:
on clickOn(doc, cssSelector, ndx)
# If no explicit index (into the matches returned by the CSS selector)
# is specified, default to 0.
if ndx is missing value or ndx = "" then set ndx to 0
# Synthesize the JavaScript command.
set jsCode to "
(function () { // Use a closure to avoid polluting the global namespace.
function doIt(t) { // Helper function
if (doIt.done) return; // Already successfully called? Ignore.
try {
// Perform the desired action - may fail if invoked too early.
document.querySelectorAll('" & cssSelector & "')[" & ndx & "].click();
} catch(e) {
return; // Return without setting the success 'flag'.
}
doIt.done=true; // Set success 'flag' as a property on this function object.
};
// Attach a listener to the window's load event for invoking the helper function then.
window.addEventListener('load', doIt);
// If the document signals readiness -- which may still be too early, we can't know --
// also try to invoke the helper function *directly*.
if (document.readyState === 'complete') { doIt(); }
})();
"
# Execute the JavaScript command in the target page.
if class of doc as text is "document" then # Safari: a «document» instance was passed
using terms from application "Safari"
tell doc to do JavaScript jsCode
end using terms from
else # Google Chrome: a «tab» instance was passed
# !! IF CHROME IS NOT INSTALLED, SIMPLY DEACTIVATE THIS `using terms from` BLOCK.
using terms from application "Google Chrome"
tell doc to execute javascript jsCode
end using terms from
end if
end clickOn
In Mac Lion: choose lock screen in lockscreen icon (Keychain Access -> Preferences --> General -> Show keychain ...), it will in screen saver mode.
In mavericks: when lock screen by above steps, it is NOT in screen saver mode. So we can not control it. I don't know why???
Then in locked screen, I tranfer event to press down key On MAVERICKS (It's OK on Mac Lion), but it seems not know about that:
on run
tell application "/System/Library/Frameworks/ScreenSaver.framework/Versions/A/Resources/ScreenSaverEngine.app" to quit
tell application "System Events" to key code 125
delay 1
tell application "System Events" to keystroke "password"
delay 1
tell application "System Events" to keystroke return
delay 5
end run
Excute above script by:
NSString *source = [NSString stringWithFormat:kAppleScriptUnlockWithPassword ,password];
// Create unlock script with password
NSAppleScript* appleScript = [[NSAppleScript alloc] initWithSource:source];
NSDictionary * errDic = nil;
// Execute script
[screenState removeAllObjects];
[appleScript executeAndReturnError:&errDic];
NSLog(#"%#", errDic);
It returns:
{
NSAppleScriptErrorAppName = "System Events";
NSAppleScriptErrorBriefMessage = "Can\U2019t make {1, \"\"} into type text.";
NSAppleScriptErrorMessage = "System Events got an error: Can\U2019t make {1, \"\"} into type text.";
NSAppleScriptErrorNumber = "-1700";
NSAppleScriptErrorRange = "NSRange: {92, 20}";
}
Do you have any idea about it?
Please help me.
Thanks
keystroke 125 inserts 125 as text. Try using key code instead:
quit application "ScreenSaverEngine"
tell application "System Events"
key code 125
delay 1
keystroke "password" & return
end tell
I'm trying to create an OSX application which would be a replica of On Screen keyboard. Is it possible to insert some text into the cursor position of another active application? Thanks in advance!
It is possible. Accessibility enables to change content of other applications, but your app can't be sandboxed and thus not available via AppStore.
CFTypeRef focusedUI;
AXUIElementCopyAttributeValue(AXUIElementCreateSystemWide(), kAXFocusedUIElementAttribute, &focusedUI);
if (focusedUI) {
CFTypeRef textValue, textRange;
// get text content and range
AXUIElementCopyAttributeValue(focusedUI, kAXValueAttribute, &textValue);
AXUIElementCopyAttributeValue(focusedUI, kAXSelectedTextRangeAttribute, &textRange);
NSRange range;
AXValueGetValue(textRange, kAXValueCFRangeType, &range);
// replace current range with new text
NSString *newTextValue = [(__bridge NSString *)textValue stringByReplacingCharactersInRange:range withString:newText];
AXUIElementSetAttributeValue(focusedUI, kAXValueAttribute, (__bridge CFStringRef)newTextValue);
// set cursor to correct position
range.length = 0;
range.location += text.length;
AXValueRef valueRef = AXValueCreate(kAXValueCFRangeType, (const void *)&range);
AXUIElementSetAttributeValue(focusedUI, kAXSelectedTextRangeAttribute, valueRef);
CFRelease(textValue);
CFRelease(textRange);
CFRelease(focusedUI);
}
This code does not check for errors and makes assumption that focused element is text area.
Not sure if this helps, but in Applescript you can do something like
tell application "System Events"
keystroke "Stuff here"
end tell
So maybe you can try call that within cocoa using NSApplescript or using NSTask and run
osascript -e 'tell application "System Events" to keystroke "Stuff here"'