Closing an Open List

This is incredible basic but I just cannot find out how to close a list even when a default value has been selected other of course than clicking OK. The following bit of code opens a list and defaults to a selection for the first item. what I would like to do is keep it up for a couple of seconds and close using the default selection.


set OptionList to {"1 minute", "5 minutes", "15 minutes", "1 Hour", "4 Hours", "1 Day", "1 Week", "1 Month"}	
	activate
	set TimeInt to choose from list OptionList with title "Intervals" with prompt "What's the Time interval?" default items "1 minute"

There are too many items to use a dialog box so giving up after is not an option.

Thanks

Peter

Thank you very much for getting back to me and the comment about not being able to close the window programmatically. Appreciate that and I guess my original post lacked in description, as what I need to do is click the OK button. I have tried to address that issue but with time out and what I thought would be click on OK as is shown in the following script . But it fails it does not understand the click message


set OptionList to {"1 minute", "5 minutes", "15 minutes", "1 Hour", "4 Hours", "1 Day", "1 Week", "1 Month"}
set TimeInt to item 1 of OptionList
set TimeInt to choose from list OptionList with title "Intervals" with prompt "What's the Time interval?" default items "1 minute"
with timeout of 2 seconds
	tell application "System Events"
		click button "OK" of window "Intervals" of current application
	end tell
end timeout


You cannot press the button with GUI scripting because the dialog window suspends the execution until the user presses a button.

However you can accomplish your request with Shane’s Dialog Toolkit Plus script library

Download the library and put the .scptd file into ~/Library/Script Libraries.

This is a simple example. Unlike choose from list the list appears as a popup button.

The chosen interval is in the variable chosenInterval

The script gives up after 5 seconds and returns the default value

use AppleScript version "2.4"
use scripting additions
use script "Dialog Toolkit Plus" version "1.1.0"

set accViewWidth to 150
set {theButtons, minWidth} to create buttons {"Cancel", "OK"} default button "OK" cancel button "Cancel" with equal widths
if minWidth > accViewWidth then set accViewWidth to minWidth -- make sure buttons fit
set {timePopup, popupLabel, theTop} to create labeled popup {"1 minute", "5 minutes", "15 minutes", "1 Hour", "4 Hours", "1 Day", "1 Week", "1 Month"} left inset 0 bottom 0 popup width 100 max width accViewWidth label text "Intervals" popup left 0 initial choice "1 minute"
set allControls to {timePopup, popupLabel}
set {buttonName, controlsResults} to display enhanced window "What's the Time Interval" acc view width accViewWidth acc view height theTop acc view controls allControls buttons theButtons initial position {1000, 100} giving up after 5 with align cancel button
set {chosenInterval, unused} to controlsResults

Hi Stefan

Thank you once again, should have guessed it was past GUI. Installed as you suggested and the script you provided runs but I had to cut out the command “align with cancel button” otherwise the popup opens and closes immediately before a selection can be made. It looks as if I can use what you provided but wondered if I was missing something?

Peter.

You can also do it using my Myriad Tables Lib.

use AppleScript version "2.4"
use scripting additions
use script "Myriad Tables Lib" version "1.0.9"

set OptionList to {"1 minute", "5 minutes", "15 minutes", "1 Hour", "4 Hours", "1 Day", "1 Week", "1 Month"}
display table with data OptionList with title "Intervals" with prompt "What's the Time interval?" initially selected rows {1} giving up after 5 with double click means OK
# timed out result:
--> {rows selected:{1}, values selected:{"1 minute"}, values returned:{"1 minute", "5 minutes", "15 minutes", "1 Hour", "4 Hours", "1 Day", "1 Week", "1 Month"}, button number:0, timed out:true, final position:{1153.0, 301.0, 217.0, 307.0}}
# clicked row result:
--> {rows selected:{5}, values selected:{"4 Hours"}, values returned:{"1 minute", "5 minutes", "15 minutes", "1 Hour", "4 Hours", "1 Day", "1 Week", "1 Month"}, button number:1, timed out:false, final position:{1153.0, 301.0, 217.0, 307.0}}

The catch is that under 10.14 you can’t run that in Script Editor – you need to do it in Script Debugger. And installing the library under current betas of 10.15 means manually removing the quarantine attributes.

Just for completeness, there’s this little trick:


set OptionList to {"1 minute", "5 minutes", "15 minutes", "1 Hour", "4 Hours", "1 Day", "1 Week", "1 Month"}

activate
do shell script "osascript -e 'delay 2' -e 'tell application \"System Events\" to keystroke return' > /dev/null 2>&1 & "
set TimeInt to (choose from list OptionList with title "Intervals" with prompt "What's the Time interval?" default items {"1 minute"})

And just hope that the user hasn’t already made a choice, with another dialog now showing :o

I don’t follow you. :confused:

Consider this code:

set OptionList to {"1 minute", "5 minutes", "15 minutes", "1 Hour", "4 Hours", "1 Day", "1 Week", "1 Month"}

activate
do shell script "osascript -e 'delay 2' -e 'tell application \"System Events\" to keystroke return' > /dev/null 2>&1 & "
set TimeInt to (choose from list OptionList with title "Intervals" with prompt "What's the Time interval?" default items {"1 minute"})
display dialog "Should I wipe your hard disk?"
...

If the user clicks OK inside 2 seconds, System Events will OK the second dialog.

Yeah. You got me. :frowning: One can stick in a delay between the dialogs so that the second one doesn’t catch the return, but the return still goes somewhere. The best I can think of in a hurry is:

set OptionList to {"1 minute", "5 minutes", "15 minutes", "1 Hour", "4 Hours", "1 Day", "1 Week", "1 Month"}

activate

do shell script "osascript -e 'delay 2' -e 'tell application \"System Events\" to keystroke return' > /dev/null 2>&1 & "
set t1 to (current date)
set TimeInt to (choose from list OptionList with title "Intervals" with prompt "What's the Time interval?" default items {"1 minute"})
set unusedTimeout to 2.6 - ((current date) - t1)
if (unusedTimeout > 0) then display dialog "Look out! Behind you!" buttons {"•"} default button 1 giving up after unusedTimeout
display dialog "Should I wipe your hard disk?"

:rolleyes:

:lol:

First thanks everyone for your help. However other than Stefan’s suggestion the others work if run from the Script Editor but not as compiled scrips.

Nigel’s suggestion and one I had managed to build (see below) work if run from Script Editor but not as a compiled scrip. There is a physical difference that may account for this in that if I run either Nigel’s or mine as complied scrips the list boxes are not selected and they simply hang. As it happens Stefan’s pop up is not selected when run as a compiled scrip but it works.


set OptionList to {"1 minute", "5 minutes", "15 minutes", "1 Hour", "4 Hours", "1 Day", "1 Week", "1 Month"}
activate
set TimeInt to item 1 of OptionList
--activate window "intervals"
--################ A workaround to close the Time interval selection to default without clicking OK
try
	with timeout of 2 seconds
		set TimeInt to choose from list OptionList with prompt "What's the Time Interval" with title "Intervals" default items "1 minute"
		
	end timeout
on error
	tell application "System Events"
		tell process "Script Editor"
			try
				click button "OK" of window "intervals"
			end try
		end tell
	end tell
end try
--######################

Obviously if I could figure out how to select the list box when it is opened as a compiled scrip that may let it work.

Thanks again

Peter

My suggestion shouldn’t be taken too seriously. Basically, what you want isn’t sensibly possible with the standard ‘choose from list’ dialog because once the script’s invoked the dialog, it can’t move on until the dialog’s dismissed, which means it can’t dismiss the dialog itself. My suggestion sets an outside agency going before calling the dialog. That agency is an independently run script which waits for a couple of seconds, imitates the pressing of the Return key, and throws its result away without reporting back. As Shane’s pointed out, if the user him/herself dismisses the dialog before the end of the “giving up” period, there’s nothing to stop the Return key effect from happening anyway. Your best hope, if you can make it work, is to use a custom dialog provided by one of Shane’s libraries mentioned above.

Thank you again, given Shanes restrictions (using Script Debugger etc) I may as well stay with Stefan’s solutions as I mentioned it worked as a stand alone routine, I will see what happens when it gets in the rest of my script.

In case you’re not aware, Script Debugger is free running in Lite mode, which is all you need in this case.

Hi Peter.

I’ve been looking more closely at your workaround. It’s pretty cool! :cool:

If I remember correctly, ‘with timeout’ applies when the script’s waiting for a response from another application. So if the dialog’s displayed by an application other than the one running the script, the timeout should work. Once all the necessary permissions have been granted, this demo version works for me in both Script Editor and Script Debugger, as an application, and as a compiled script in Script Menu:

on chooseFromTimeOptions()
	set OptionList to {"1 minute", "5 minutes", "15 minutes", "1 Hour", "4 Hours", "1 Day", "1 Week", "1 Month"}
	
	set TimeInt to {item 1 of OptionList}

	--################ A workaround to close the Time interval selection to default without clicking OK
	set intervals to "Intervals"
	try
		with timeout of 3 seconds
			tell application "Finder"
				activate
				set TimeInt to choose from list OptionList with prompt "What's the Time Interval" with title intervals default items TimeInt
			end tell
		end timeout
	on error
		tell application "System Events"
			tell (application process "Finder")
				set frontmost to true
				try
					click button "OK" of window intervals
				end try
			end tell
		end tell
	end try
	
	--######################
	if (TimeInt is false) then
		say "false"
	else
		say item 1 of TimeInt
	end if
end chooseFromTimeOptions

chooseFromTimeOptions()

Hi Nigel

Apologise for the delay in acknowledging your reply, I have been away, any way will try incorporating your scrip into my routine. Must admit I had given up and reverted to a Dialog Box with a default value as in practice its unlikely to change between iterations although it may between days. Very clumsy but will try your suggestion.


display dialog "This allows the selection of the time interval for the Technical Analysis the default is set at 1 Day" & return & "1 Minute =0" & return & "5 Minutes =1" & return & "15 Minutes = 2" & return & "1 hour =3" & return & "4 hours =4" & return & "1 day =5" & return & "1 week =6" & return & "1 month =7" default answer "5" giving up after 5
	set Trx to text returned of result as text

Thanks again

Peter

Here @Nigel Garvey has already shown one way to auto-collapse the Choose From List dialog. But as @Shane Stanley correctly notes, “And just hope that the user hasn’t already made a choice, with another dialog now showing …”

Therefore, I want to show users a completely different approach to solve this problem. It is stable and uses the default selection of multiple non-sequential list items. I think this one will be useful to users, and @Nigel Garvey won’t scold me for uselessly bringing up an old topic.


-- Implementing Choose From List dialog with Giving Up After N seconds functionality
-- written: by me just now

set OptionList to {"1 minute", "5 minutes", "15 minutes", "1 Hour", "4 Hours", "1 Day", "1 Week", "1 Month"}

with timeout of 2 seconds
	try
		set TimeInt to choose from list OptionList with title "Intervals" with prompt "What's the Time interval?" default items {item 1 of OptionList, item 3 of OptionList} with multiple selections allowed
		TimeInt
	on error number -2753
		tell application "System Events" to tell (first process whose frontmost is true)
			if exists window "Intervals" then click button "OK" of window "Intervals"
		end tell
		set TimeInt to {item 1 of OptionList, item 3 of OptionList}
	end try
end timeout

Note: If anyone is unclear why (and how) this code works, I can add an explanation.