Articles Archive
Articles Search
Director Wiki
 

Auto-indexing User Text Entry

September 12, 1999
by Pat McClellan

Dear Multimedia Handyman,

I have some problems regarding programming a children's dictionary. I'll have all of the words in a field, and I want to create dynamic input so if the user types "appl", the dictionary matches the first few letters and shows the word "apple". It's giving me a headache trying to figure it out, appreciate any help.

Alvin Gan

Dear Alvin,

Since this is a children's dictionary, you're probably OK storing the words in a field. (For a larger project, I'd recommend using a database xtra.) Storing the words in a field is an easy way to add and delete the words, but when we get down to processing it, you'll want to move the words from the field into a list. There are several list operations that are perfectly suited to our needs.

It's fairly easy to convert a field into a list, but that process kind of depends on how you format the string in the field. If your words are entered into field "wordlist" so that it looks like a list...

["apartment", "apple", "apricot", "appreciate"]

... then you can convert it to a list like this:

myList = value(field "wordlist")

It's more likely that you'll want to build your list of words without having to worry about all the quote marks and adherance to list syntax. So, if your field looks like this instead...

apartment
apple
apricot
appreciate

... you'll need to use a utility handler to build your list. This will do the trick:

on buildList fieldName
  global gMyList
  
  gMyList = []
  textString = field fieldName
  set the itemDelimiter = RETURN
  lineCount = the number of lines in textString
  
  repeat with whichLine = 1 to lineCount
    add gMyList, line whichline of field fieldname
  end repeat
  
  sort gMyList
  
end

This handler takes all of the words in the field and adds them to a list, stored in the global variable gMyList. Note that the last line sorts the list alphabetically, which means that you really don't have to worry too much about entering the words in alphabetical order. Sorting has another very valuable function in a list. It makes it extremely fast to search through.

Here's a demo which uses the features we want to achieve. I'd suggest entering some words into it right away. Might as well use the ones I've mentioned: apple, appreciate, apricot, apartment. Note that you don't have to worry about alphabetical order. The list sort takes care of that.

Download a sample movie in Mac or PC Format.

Another key list function is one called findPosNear(list, value). This command requires that you provide the list name, and a value to check. So, if we test it on gMyList...

put findPosNear(gMyList, "apricot")
--3

... it returns the integer position in the list occupied by "apricot". You could actually do that same thing with getPos(), but findPosNear does something a little more sophisticated. Try this:

put findPosNear(gMyList, "ap")
--1
put findPosNear(gMyList, "app")
--2
put findPosNear(gMyList, "appr")
--3

What we're seeing is that each incremental letter that we add to the text string changes the position in the list. That's the behavior we're looking for. What we need is the actual word at that position of the list, so it's pretty easy to retrieve that. One thing to note about findPosNear, try this:

put findPosNear(gMyList, "b")
--5

When the test string is greater than the last item in the list, it will return a number that is 1 more than the count of your list. If you try to do a getAt function on the list with this number, you'll get an error message. So, we'll have to make sure that we allow for that possiblity.

The only other thing we've got to figure out is how to run that findPosNear check after each letter is entered. For that, we're write an autoIndex behavior. This behavior will need to run that findPosNear check every time a new letter is added to the field. Luckily, there's an event that triggers on keyUp, so we'll put all of the findPosNear stuff there.

-- autoIndex behavior
-- copyright © 1999, ZZP Online, LLC
-- free use for Director Online readers
global gMyList
property pMyMem, pResultField
on beginSprite me
  pMyMem = sprite(me.spriteNum).member
end beginSprite
on keyUp me
  input = pMyMem.text
  index = findPosNear(gMyList, input)
  
  if index > gMyList.count then
    nearestWord = "not available"
  else
    nearestWord = gMyList[findPosNear(gMyList,input)]
  end if
  
  if nearestWord contains input then
    pResultField.color = rgb(0,0,0)
    pResultField.text = nearestWord
  else 
    pResultField.color = rgb(128,128,128)
  end if
  
end keyUp
on getPropertyDescriptionList me
  set pdlist to [:]
  addprop pdlist, #pResultField, [#comment:¬
    "Result display field:", #format:#field, #default:1]
  return pdlist
  
end getPropertyDescriptionList

I added a little flourish of color effect to the output field. If the input is not contained within any of the words in our list, then the color of the result field is changed to gray. It a nice effect I think.

Good luck with your program.

Patrick McClellan is Director Online's co-founder. Pat is Vice President, Managing Director for Jack Morton Worldwide, a global experiential marketing company. He is responsible for the San Francisco office, which helps major technology clients to develop marketing communications programs to reach enterprise and consumer audiences.

Copyright 1997-2024, Director Online. Article content copyright by respective authors.