How to script the selection of an option from a popup menu?

I wish to use a script to set the language (dictionary) of the Spell Checker in some application, e. g. Mail. I have tried the following (test run within Script Editor):


set CurApp to name of current application
tell application "System Events" to tell process CurApp
	keystroke ":" using command down
	delay 1
	tell window "Spelling and Grammar"
		click pop up button 1
		click menu item "Swedish" of menu 1 of pop up button 1
		click (close button)
	end tell
end tell

When I execute the script, the Spelling window pops up, as expected, but then nothing more happens until I perform some action. The event log so far is:

Almost any action is enough to trigger the continuation, e.g. hitting the Escape key. After that, a pop up message appears:

The following is added to the event log:

What is wrong with my script? Why does the script seem to stall in the execution of “click pop up button 1” although the result of that execution is visible on the screen?

Model: Mac Mini (Intel)
AppleScript: 2.0.1
Browser: Safari 525.27.1
Operating System: Mac OS X (10.5)

Hi, pwannh
I dont know apple script. But I want to learn and i like playing with it.
So here is what I got after playing with your script for some time.
(I did not have Swedish language installed. So i tried “Dansk” language)

tell application "System Events" to tell process (name of current application)
	keystroke ":" using command down
	delay 1
	tell window "Spelling and Grammar"
		keystroke "Dansk"
		keystroke return
                click pop up button 1
		end tell
end tell

The only problem is I could not close the “Spelling and Grammar” window.

Whoever corrects pwannh’s script please bother to tell me why does my script work the way it does—I mean, i have used keystroke “Dansk” first and “click pop up button1” afterwards.

Thanks chris2 - that really helped me!

I apologize for an error in my script - “Swedish” should have been “Svenska”. But that doesn’t really affect the problem.

I found a simple way to complete the script so as to close the spelling window - see below.


set CurApp to name of current application
tell application "System Events" to tell process CurApp
	keystroke ":" using command down
	delay 1
	tell window "Spelling and Grammar"
		keystroke "Svenska"
		keystroke return
		click pop up button 1
		click button 1 -- click close button
	end tell
end tell

But I would still like to know what was wrong with the original script. The above script is really screwy.

And also - is there any documentation that would have helped me find the solution on my own? I have spent considerable time looking for it, in vain.

I tried to save the script and assign it a keyboard shortcut. It did not work. Then i saved it as application and then i did several other things till i found out that the script works only when run from the script menu. Is there no other way to run this script? Can a keyboard shortcut be assigned to a script which has to be run from script menu alone?
(thanks, pwannh for calling my script “screwy” :D.)

Dear chris2:

Please accept my apologies for calling your script “screwy”. It was sloppy; what I meant was that if there is no more straightforward way to write a script to perform these actions, then something in the AppleScript logic or in the construction of these UI elements is, let’s say, twisted. I certainly appreciate your efforts leading to a solution even under such circumstances.

I am still puzzled because I have read several examples on the web doing precisely what my script does. And I join with chris2 in asking the same questions he is asking. Some expert out there - please help!

Hello,
any replies please?

I do not think Apple’s builtin, global script menu has support for keyboard shortcuts. Try FastScripts or some of the various “launcher” applications.

Thanks chrys for the reply. Can anyone answer the other question related to the script–why it is “screwy”?

Hello I made some tests.

set curApp to "TextEdit" --to name of current application
tell application curApp to activate
tell application "System Events" to tell process curApp
	set knt to count of windows
	keystroke ":" using command down
	delay 1
	if (count of windows) > knt then
		set nw1 to name of window 1
		try
			tell window nw1 --"Spelling and Grammar" is "Orhographe" in France
				keystroke "Svenska"
				keystroke return
				click pop up button 1 --of group 1
			end tell -- window
			log "ok"
			click button 1 of window nw1 (* close the window *)
		on error errmsg number nmbr
			log nmbr & " -- " & errmsg
			click button 1 of window nw1 (* close the window *)
		end try
	end if
end tell -- application

The log report stated:

tell application “TextEdit”
activate
end tell
tell application “System Events”
count every window of process “TextEdit”
1
keystroke “:” using command down
count every window of process “TextEdit”
2
get name of window 1 of process “TextEdit”
“Orthographe”
keystroke “Svenska”
keystroke "
"
click pop up button 1 of window “Orthographe” of process “TextEdit”
(1, – , NSReceiverEvaluationScriptError: 4)
click button 1 of window “Orthographe” of process “TextEdit”
button 1 of window “Orthographe” of application process “TextEdit”
end tell

So, I edited one instruction.

set curApp to "TextEdit" --to name of current application
tell application curApp to activate
tell application "System Events" to tell process curApp
	set knt to count of windows
	keystroke ":" using command down
	delay 1
	if (count of windows) > knt then
		set nw1 to name of window 1
		try
			tell window nw1 --"Spelling and Grammar" is "Orhographe" in France
				keystroke "Svenska"
				keystroke return
				click pop up button 1 of group 1
			end tell -- window
			log "ok"
			click button 1 of window nw1 (* close the window *)
		on error errmsg number nmbr
			log nmbr & " -- " & errmsg
			click button 1 of window nw1 (* close the window *)
		end try
	end if
end tell -- application

This time, the log report is:

tell application “TextEdit”
activate
end tell
tell application “System Events”
count every window of process “TextEdit”
1
keystroke “:” using command down
count every window of process “TextEdit”
2
get name of window 1 of process “TextEdit”
“Orthographe”
keystroke “Svenska”
keystroke "
"
click pop up button 1 of group 1 of window “Orthographe” of process “TextEdit”
pop up button 1 of group 1 of window “Orthographe” of application process “TextEdit”
(ok)
click button 1 of window “Orthographe” of process “TextEdit”
button 1 of window “Orthographe” of application process “TextEdit”
end tell

So, I know that all the code is ‘legal’ but the keystroke is not sent to the menu but to the TextEdit document :frowning:

Yvan KOENIG (from FRANCE jeudi 5 février 2009 14:31:35)

yes, you are right. That also happened when I ran a similar script in Script Editor. The text got pasted into Script Editor window instead of pop up menu of “Spelling and Grammar” window?

And if change your script lines from

keystroke "Svenska"
               keystroke return
               click pop up button 1 
click pop up button 1
keystroke "Svenska"
               keystroke return

it works perfectly.
so is this to be taken as applescript’s normal behaviour?

One more observation:

set curApp to name of current application
tell application curApp to activate
tell application "System Events"
	tell process curApp
		set knt to count of windows
		keystroke ":" using command down
		delay 1
		if (count of windows) > 1 then
			set nw1 to name of window 1
			try
				tell window nw1
					delay 1
					keystroke "Dansk"
					keystroke return
					click pop up button 1
				end tell
				log "ok"
				click button 1 of window nw1
			on error errmsg number nmbr
				log nmbr & " -- " & errmsg
				click button 1 of window nw1 (* close the window *)
				end try
		end if
	end tell
end tell

Change your language back to english in “spelling and grammar” window and now if you modify the above script to

tell window nw1
					delay 1
					keystroke "Dansk"
                                        delay 1
					keystroke return
					click pop up button 1
				end tell

you will see that the script types the word “Dansk” in Script Editor window.
I guess what happens is the “spelling and grammar” loses focus (it does not remain the active window to which the script must send keys).

For tests I used this one:


set curApp to "TextEdit" --to name of current application
tell application curApp to activate

set myLanguage to "Svenska"
if curApp is not "Script Editor" then
	tell application "System Events" to tell process curApp
		set knt to count of windows
		keystroke ":" using command down
		delay 0.2
		if (count of windows) > knt then
			set nw1 to name of window 1
			try
				tell window nw1
					if item 1 of (get value of pop up button of group 1) is not myLanguage then
						click pop up button 1 of group 1
						click menu item myLanguage of menu 1 of pop up button of group 1
					end if
				end tell
				log "ok"
				click button 1 of window nw1 (* close the window *)
			on error errmsg number nmbr
				log nmbr & " -- " & errmsg
				click button 1 of window nw1 (* close the window *)
			end try
			--click button 1 of window nw1 (* close the window *)
		end if
	end tell -- application
end if

For real use replace it by:


set curApp to "TextEdit" --to name of current application
tell application curApp to activate

set myLanguage to "Svenska"
if curApp is not "Script Editor" then
	tell application "System Events" to tell process curApp
		set knt to count of windows
		keystroke ":" using command down
		delay 0.2
		if (count of windows) > knt then
			set nw1 to name of window 1
			try
				tell window nw1
					if item 1 of (get value of pop up button of group 1) is not myLanguage then
						click pop up button 1 of group 1
						click menu item myLanguage of menu 1 of pop up button of group 1
					end if
				end tell
			end try
			click button 1 of window nw1 (* close the window *)
		end if
	end tell -- application
end if

Now, I’m searching the resource file containing the localized names of the window so I will not have to rely on the count of windows.

Yvan KOENIG (from FRANCE vendredi 6 février 2009 11:42:48)

Thanks very much to both chris2 and Yvan Koenig (YK). I have tried your scripts, but strangely I often get different results. I will go through them one by one below. I will refer to your scripts by the author and a timestamp of the post in the form yymmdd-hhmmss-n, where n is a script sequence number within the post. Date and time is as shown for the post, but I suspect that these are shown in my timezone, which is GMT -10:00 (Hawaii). Sorry for the trouble, but you will have to convert to yours to identify the script (mmss is a good “checksum”).

  1. YK 090205-033137-1
    Curiously, I do not get the exception that you get, but the execution is erroneous:
    “Svenska” is put into TextEdit’s text area, the popup menu of languages (just the menu, not the Spelling window!) remains on the screen, and the language is not set.

  2. YK 090205-033137-2
    Different behavior here too. Now I DO get an exception (only the interesting part shown):

Again, “Svenska” entered in text, language not set.

  1. chris2 090205-034607
    When I apply this modification to YK 090205-033137-1, yes, the script seems to work!

  2. chris2 090205-045316
    My results agree exactly with yours.

  3. YK 090206-124359-1
    Throws exception, language not changed.

  1. YK 090206-124359-2
    No effect (no exception, no language change).

Summary:
Quite confusing, isn’t it? My best guess is some race condition, i.e. concurrent threads and events that cause different effects depending on precisely when they occur. Possibly some difference in configuration? I have Mac OS 10.5.6, all the latest updates, Script Editor 2.2.1 (100.1), AppleScript 2.0.1, TextEdit 1.5 (244).

My eventual goal is to find a solution that will work together with several applications such as TextEdit, Mail, Safari and more. It seems that they all invoke the same spell checker. I know how to add code to the script to allow me to select one of my favorite three languages. I would like to fire up the script with a keystroke. I just don’t know the mechanics for making a keystroke run a given script. Any help would be appreciated.

Hi pwann,
Yuan Koenig 's last two scripts dont work for me either. Perhaps, because of the fact that he uses a non-english language in his system.

To run an applescript with a keystroke, I recommend Butler. Its slightly complicated to use but its more stable than Quicksilver. As I had asked earlier in this thread, how to assign a shortcut to a script which has to be run alone from Scripts menu alone, the only answer that I have as of now to that question is to write another script using UI method and assign a shortcut to it rather than assigning a shortcut to the original script.

This is what I wrote

It appears that the window in not built the same way in os X 1.4 ans in OS X 1.5

In 1.4 the popup is in a group
In 1.5 it isn’t.
Here is a version which take care of this difference.


set curApp to "TextEdit" --to name of current application
tell application curApp to activate

set myLanguage to "Svenska"
if curApp is not "Script Editor" then
	tell application "System Events" to tell process curApp
		set knt to count of windows
		keystroke ":" using command down
		delay 0.2
		if (count of windows) > knt then
			set nw1 to name of window 1
			try
				tell window nw1
					if my quelOS() < "1500" then
						if item 1 of (get value of pop up button of group 1) is not myLanguage then
							click pop up button 1 of group 1
							click menu item myLanguage of menu 1 of pop up button of group 1
						end if
					else
						if item 1 of (get value of pop up button) is not myLanguage then
							click pop up button 1
							click menu item myLanguage of menu 1 of pop up button
						end if
					end if -- quelOS
				end tell
			end try
			click button 1 of window nw1 (* close the window *)
		end if
	end tell -- application
end if

--=====

on quelOS()
	local hexData, hexString
	set the hexData to system attribute "sysv"
	set hexString to {}
	repeat 4 times
		set hexString to ((hexData mod 16) as string) & hexString
		set hexData to hexData div 16
	end repeat
	return hexString as string
end quelOS

--===== 

Yvan KOENIG (from FRANCE samedi 7 février 2009 14:20:55)

Hi YK.
no change. does not work. no error messages.

Text edit 1.5(244)

YK 090207-032102: I get the same result as chris2: no error, but language does not change.

chris2: your script 090205-045316 worked fine, but only when run in Script Editor. If I change the first line to “set curApp to “TextEdit””, it no longer works (“Dansk” entered in text area, popup menu remains open, language not changed).

I am getting very suspicious about GUI scripting - does it really work reliably? Is there a good, complete reference manual on using AppleScript to control GUI’s?

I will make tests with Mac OS X 10.5.6 tomorrow

Under 10.4.11 it behaves flawlessly.

GUI scripting is a bit boring because:

¢ menus may change from on program’s version to another one (Pages and Numbers for instance)
¢ the structure of some GUI elements may change given the OS version.
Here there is a problem with the popup which is in a group in 10.4.1 and seems to fon’t in 10.5

For Pages and Numbers, some GUI items must be triggered with
click button theButton of radio group 1 under 10.4
but must be triggered with
click checkbox theButton of radio group 1 under 10.5

And sometimes it’s difficult to write localization independant scripts.

Yvan KOENIG (from FRANCE samedi 7 février 2009 23:25:38)

this checks, whether the OS is less then 15.0.0 :wink:

For your purpose this version check might be sufficient


(system attribute "sysv") mod 4096 div 16 --> returns 4 for Tiger and 5 for Leopard

sorry i dont understand which script is “090205-045316”. I think the times in different countries have to be adjusted for to understand it. On the right hand side of a post, there is always a post number like ("#12, #13). You should refer to that in future. I would like to know why you are not using the first script that I wrote (in post #2 and which you modified in post#3 for the close button). That seems to work very reliably.

As much as I know, GUI scripting is to be used as last resort when normal scripting is not possible.