So I have a text field that I would like to run the following code when the text changes (you can tell it’s a workaround for not being able to figure out drop areas for files but maybe I’m on the right path):
set single_string to (stringValue() of files_drop) as string
set AppleScript's text item delimiters to {return, linefeed, return & linefeed, linefeed & return}
set pre_list to text items of single_string as list
set AppleScript's text item delimiters to {}
set list_text to ""
repeat with i from 1 to number of items in pre_list
set this_item to item i of pre_list
set Applescript's text item delimiters to "/"
set text_item to last text item of this_item as text
set Applescript's text item delimiters to ""
set list_text to list_text & text_item & return & return
end repeat
files_list's setStringValue_(list_text)
files_drop's setHidden:1
files_list's setHidden:0
files_drop's displayIfNeeded()
files_list's displayIfNeeded()
The problem is in the interface builder the only options are sent on end editing and sent on enter only. Is there a way to make it so that this routine runs once the text changes (like altering the properties of the NSTextField on application launch for instance?) I tried with an NSTimer forcing a tab/return, but I can’t think of a good condition to be present to make sure it doesn’t keep running.
It’s pretty easy to set up. In Interface Builder, just set the delegate of your NSTextField(s) to your App Delegate object, and then add something like this to your AppDelegate.applescript file:
property aTextField : missing value
property aTextField2 : missing value
property aTextLabel : missing value
on controlTextDidChange_(aNotification)
if aNotification's object() is aTextField then
-- run whatever you want to,
-- but here is an example of setting a label's string to the field's new string
set newText to aTextField's stringValue()
aTextLabel's setStringValue_(newText)
end if
if aNotification's object() is aTextField2 then
-- run whatever you want to,
-- but here is an example of setting a label's string to the field's new string
set newText to aTextField2's stringValue()
aTextLabel's setStringValue_(newText)
end if
end controlTextDidChange_
Thanks… but I think i’m missing some steps, the textfields value is bound to netBootNameTextfield’s value.
On send (which is on end editing) the below action is run:
Changing from (sender) to (aNotification) didn’t work… So what are the steps to register aNotification?
-- Make sure a name is specified for the NetBoot Image, error if not.
on netBootName_(sender)
-- If textfield is empty
if netBootNameTextField is missing value then
-- Set netBoot Name
set my netBootNameTextField to selectedOSdmgVersion & " AutoCasperNBI"
-- Display error to user
display dialog "Please select a Name for the NetBoot Image" with icon 0 buttons {"OK"}
--Log Action
set logMe to "Error: Name required for NetBoot Image"
-- Log To file
logToFile_(me)
else
--Log Action
set logMe to "Name: " & netBootNameTextField
-- Log To file
logToFile_(me)
end if
end netBootName_
The app i’m writing has various textfield options in the XIB’s, to close there are buttons.
I’ve created an action for the button that re-runs the sender actions for each textfield, this then has logic to alert the user or proceed… seems to work for me.
As an example, here’s the Time Server action:
-- Bound to Time Server Text field
on timeServerCheck_(sender)
-- If textfield is empty
if timeServerSelected is missing value then
-- Set netBoot Name
set my timeServerSelected to "time.apple.com"
-- Display error to user
display dialog "Please enter a Time Server" with icon 0 buttons {"OK"}
--Log Action
set logMe to "Error: Please enter a Time Server"
-- Log To file
logToFile_(me)
-- Update plist with selection
tell defaults to setObject_forKey_(timeServerSelected, "timeServerSelected")
-- Set to false so we don't proceed
set closeButtonPreCheckPassed to false
else
--Log Action
set logMe to "Time Server: " & timeServerSelected
-- Log To file
logToFile_(me)
-- Update plist with selection
tell defaults to setObject_forKey_(timeServerSelected, "timeServerSelected")
end if
end timeServerCheck_
That would trigger when enter was pressed or another text filed, but not on clicking the XIB’s “Close” push button.
That now has an action that does the below, therefore rechecking where values are needed they are set.
-- Make sure all variables are set if enabled, if passed close options window
on closeOptionsWindowCheck_(sender)
-- reset value
set closeButtonPreCheckPassed to true
-- Verify that the description field has a value & reset & prompt if not
netBootDescriptionCheck_(me)
-- Bound to NetBoot Image Resize value
netBootImageExpandEnteredValue_(me)
-- Check the value entered in the ARD Username textfield
checkardUsername_(me)
-- Check the value entered in the ARD Password textfield
checkardPassword_(me)
-- Check the value entered in the vnc Password textfield
checkvncPassword_(me)
-- Check that a custom desktop image has been selected
checkcustomDesktopImagePath_(me)
-- Bound to Time Server Text field
timeServerCheck_(me)
-- Set to boolean of value
set closeButtonPreCheckPassed to closeButtonPreCheckPassed as boolean
-- Proceed if we've passed precheck
if closeButtonPreCheckPassed is true then
-- reload options from plist
retrieveDefaults_(me)
-- close options window
optionsWindow's orderOut_(null)
-- enable options
set my optionWindowEnabled to true
end if
end closeOptionsWindowCheck_
There’s nothing special you need to do to get controlTextDidChange working. I’ll list the steps in order, starting from scratch…
Create a new Cocoa-AppleScript application. Name it whatever you want
Under the IBOutlets comment, Add this to your AppDelegate.applescript file (without quotes): “property testTextField : missing value”
Open your MainMenu.xib file, add a new NSTextField from the object library to your NSWindow
Right-click on the NSTextField you just added to the NSWindow.
Click and drag a connection from the little circle next to “New Referencing Outlet” to the App Delegate (blue cube) object
Choose “testTextField” for the Referencing Outlet for the NSTextField
Right-click the NSTextField again and click and drag the little circle next to “delegate” (under Outlets) to the App Delegate (blue cube) object
Add the following handler to your AppDelegate.applescript file (after applicationWillFinishLaunching and before applicationShouldTerminate):
on controlTextDidChange_(aNotification)
if aNotification's object() is testTextField then
log "Handler is being called every time the string changes"
end if
end controlTextDidChange_
Run your project, edit the contents of the text field (either by typing something in there or by dragging and dropping a file from Finder into it).
Check your Debug panel in Xcode to confirm that the handler is called every time a change occurs
I try to do a sample project with this example, but don’t get an property object:
script AppDelegate
property parent : class "NSObject"
-- IBOutlets
property theWindow : missing value
property myText : missing value
property textEntered : ""
on applicationWillFinishLaunching:aNotification
-- Insert code here to initialize your application before any files are opened
end applicationWillFinishLaunching:
on controlTextDidChange:aNotification
if aNotification's object() is myText then
log "Handler is being called every time the string changes"
set newText to myText's stringValue()
textEntered's setStringValue:newText
else
log "Do nothing"
end if
end controlTextDidChange:
on applicationShouldTerminate:sender
-- Insert code here to do any housekeeping before your application quits
return current application's NSTerminateNow
end applicationShouldTerminate:
end script
always got a message “Do nothing”.
I have connected my text field in IB section “Outlets/delegate” to blue cube “Delegate”, and section “Referencing Outlets/New referencing outlet” to blue cube “Delegate/Referencing Outlets/myText” (whose declared as “property myText : missing value”).