Predictive Search

Does anyone know if an easy (and robust) way exists to make a search field in my A.S.Studio app that will search as I type, much like Finders search field?

I am trying to add this functionality to an application that pulls data from Filemaker, but does it as the user types the word he/she is searching for.

Thanks,
jON bEEBE

I’ve written the following code to do what you’re looking for. It will actively search the content of a text view for the string being typed into a text field, highlighting the string when found. I also included the framework for adding a “Find Next” feature, which searches sequentially for the search string until it reaches the end of the file, continuing back at the top when it reaches the end.

property theTextView : "" --> A persistent convenience reference to the text view
property theSearchField : "" --> A persistent convenience reference to the search field

(* * * * * * * * * * * * * Handlers * * * * * *)
on changed theObject --> Connected to the Search Field
	if name of theObject is "SearchField" then
		set {selectionStart, selectionEnd} to call method "selectedRange" of theTextView
		findNext(selectionStart, selectionStart)
	end if
end changed

on clicked theObject --> Connected to the "Find Next" button
	if name of theObject is "FindNext" then
		set {selectionStart, selectionEnd} to call method "selectedRange" of theTextView
		findNext(selectionStart, selectionEnd)
	end if
end clicked

on launched theObject --> Connected to file's owner
	set theSearchField to (text field "SearchField" of window "Window")
	set theTextView to (text view "Text" of scroll view "Scroll" of window "Window")
end launched

(* * * * * * * * * * * * * Subroutines * * * * * *)
(* Finds the next occurrence of the query in the text *)
to findNext(selectionStart, selectionEnd)
	set tmpQuery to (content of theSearchField) as string
	set tmpText to (content of theTextView) as string
	
	if (tmpQuery is not "") and (tmpText is not "") then
		(* See if there is already a selection *)
		if (selectionEnd = (length of tmpText)) then set {selectionStart, selectionEnd} to {0, 0}
		
		(* Define the text string we will be searching in *)
		if (selectionEnd + 1) < (length of tmpText) then
			set tmpText to (characters (selectionEnd + 1) through -1 of tmpText) as string
		else
			set tmpText to (character -1 of tmpText) as string
		end if
		
		(* See if the text betweeen the selection and the end of the text contains the query *)
		set {retryFromTop, tmpRange} to find_In_Text(tmpQuery, tmpText)
		
		(* Retry the search from the top of the text if the query was not found after the selection *)
		if retryFromTop then
			set tmpText to (content of theTextView) as string
			set {selectionStart, selectionEnd} to {0, 0}
			set {retryFromTop, tmpRange} to find_In_Text(tmpQuery, tmpText)
		end if
		
		(* Highlight the match if another one was found *)
		if retryFromTop is false then
			set {offsetStart, offsetEnd} to tmpRange
			set offsetStart to (offsetStart + selectionEnd)
			set offsetEnd to (offsetEnd + selectionEnd)
			tell theTextView to call method "setSelectedRange:" of it with parameters {{offsetStart, offsetEnd}}
		end if
	else
		tell theTextView to call method "setSelectedRange:" of it with parameters {{0, 0}}
	end if
end findNext

(* Locates the query in the text string and returns it's character range *)
to find_In_Text(tmpQuery, tmpText)
	if (tmpText contains tmpQuery) then
		set offsetStart to ((offset of tmpQuery in tmpText) - 1)
		set offsetEnd to (offsetStart + (length of tmpQuery))
		return {false, {offsetStart, offsetEnd}}
	else
		return {true, {0, 0}}
	end if
end find_In_Text

This should get you started, at least… :wink:
j