Connecting one text field to another

Got a LiveCode personal license? Are you a beginner, hobbyist or educator that's new to LiveCode? This forum is the place to go for help getting started. Welcome!

Moderators: FourthWorld, heatherlaine, Klaus, kevinmiller

ICCS_User
Posts: 12
Joined: Fri Dec 28, 2012 9:06 pm

Connecting one text field to another

Post by ICCS_User » Fri Dec 28, 2012 9:24 pm

How do I connect one text field to another so that a text entry in Field 1 produces a certain text output in Field 2? My information is currently contained in a lengthy two column word processor table. What I'd like is for the app to be able to match up the two columns along each row. That is, if the user types the information that matches that in column 1 in Field 1 for a certain row, then the text located in column 2 of the table for that row would appear in Field 2. I also obviously need a way to reference the information currently in my text table.

For example, suppose this were the information:
Apple...Fruit
Carrot...Vegetable
Ant...Insect

So, if the user typed "Apple" in Field 1, then Fruit would appear in Field 2.

Hope this all makes sense!
Thanks!

sturgis
Livecode Opensource Backer
Livecode Opensource Backer
Posts: 1685
Joined: Sat Feb 28, 2009 11:49 pm

Re: Connecting one text field to another

Post by sturgis » Sat Dec 29, 2012 1:36 am

Look at lineoffset() (could be done with wordoffset too)

If you have yoru sample data in field 1 (tab delimited)
field 2 is where the user can type
and field 3 is where matching data should appear, something like the following might work for you.

Code: Select all

on textchanged
   lock screen
   -- tData contains a table (tab delimted) with the information pairs
   -- place the data into a variable so its faster
   -- field 1 has my sample data, field 2 is the location I can type, field 3 contains the matchnt output.
   put field 1 into tData 
   set the itemdelimiter to tab -- set the item delimiter
   put 1 into tCount -- manually keep track of the current line number so that "for each" can be used
   repeat for each line tLine in field 2 -- the field that is being added to. Cycle through it. 
      -- check for a match with lineoffset. If there is a match, returns the line num
      -- I used tab as part of the match string as a way to force only full matches
      -- could have used wordoffset() and "set the wholematches to true" but this was easier
      put lineoffset((tLine &  tab),tData) into tLineNo
      
      --if tLineNo is greater than 0 then there was a match
      if tLineNo is not 0 then
         -- use tcount to know where to place the matching data in field 2
         -- use tLineNo to grab the correct part of the data from tData 
         -- and place the info into a variable
         put item 2 of line tLineNo of tdata into line tCount of tMatchdata
      end if
      -- increment the line counter 
      add 1 to tCount
   end repeat
   -- place the finalized dta into field 3
   put tMatchData into field 3
   unlock screen
end textchanged
There are probably other ways to handle this, but it should work ok. If you have a HUGE number of lines to deal with, a faster method might be in order though. (this one is pretty fast, but as the number of lines in field 2 and 3 grow, there could be slowdowns.. again if the number of lines is HUGE)

EDIT: Forgot to say, I placed the script into field 2 since that is where the typing will occur in my sample.

Simon
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 3901
Joined: Sat Mar 24, 2007 2:54 am
Location: Palo Alto

Re: Connecting one text field to another

Post by Simon » Sat Dec 29, 2012 2:07 am

For the exercise I did it with muti-dimensional array.
I have 2 fields, Fruit and Veg, in each one is the names of various fruits or veg.
Fill up the array:

Code: Select all

global tMultiArray
on mouseUp
   put "" into tMultiArray
   repeat for each line tLine in fld "Fruit" --each line contains a different fruit
      add 1 to x
      put tLine into tMultiArray[Fruit][x]
   end repeat
   put "" into x
   repeat for each line tLine in fld "Veg" --each line contains a different vegtable
      add 1 to x
      put tLine into tMultiArray[Veg][x]
   end repeat
end mouseUp
Then to sort through it a Search field and Result field:

Code: Select all

global tMultiArray
on returnInField
   put false into tFound --what if the seach word is not in the to fields?
   put fld "Search" into tSearch
   repeat for each line tKey in the keys of tMultiArray
      repeat for each element tContent in tMultiArray[tKey]
         if tSearch = tContent then 
            put tKey into fld "Result"
            put true into tFound
            exit repeat
         end if
      end repeat
      if tFound then exit repeat
   end repeat
   if not tFound then put "Item not found" into fld "Result"
end returnInField
Not sure if this is the best way or even if I am using a muti-dimensional array correctly but it works.
I guess offset was easier, but I got practice :D

Simon
I used to be a newbie but then I learned how to spell teh correctly and now I'm a noob!

ICCS_User
Posts: 12
Joined: Fri Dec 28, 2012 9:06 pm

Re: Connecting one text field to another

Post by ICCS_User » Sat Dec 29, 2012 2:09 am

Where do I locate my data table?

sturgis
Livecode Opensource Backer
Livecode Opensource Backer
Posts: 1685
Joined: Sat Feb 28, 2009 11:49 pm

Re: Connecting one text field to another

Post by sturgis » Sat Dec 29, 2012 2:20 am

If it were me, I'd use the array too. :)

Could probably use "split" to make the array from the existing data, but would probably adjust how the key was found.

Since it sounds like the user is looking to match multiple lines of text in 1 field with the matching pair in the other, i'd repeat through the field with the text to match, and assuming the array key is the text (apple, contents = fruit) you might be able to simply check for empty. Something like this pseudocode. it would require a diff array structure than your example though.

Code: Select all

put 1 into tCount
repeat for each line tLine in dataToLookFor
if myArray[tLine] is not empty then
  -- put the information into the correct line for use in the matching output field. 
end if
add 1 tCount
end repeat
It might also be worthwhile to have 2 arrays for dual direction conversion.

One with
array[fruit] where it contains lines listing all fruit
and array[apple] which has "fruit"

Of course even better would be an sqlite database with the pairs. Loop through and select, that way either direction can be done. Select all fruit, or select apple to get its type.

Tons of ways to skin this cat.

dunbarx
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 9663
Joined: Wed May 06, 2009 2:28 pm
Location: New York, NY

Re: Connecting one text field to another

Post by dunbarx » Sat Dec 29, 2012 2:21 am

I would have made a field that tracks its own contents using keydown messages. This can check the contents of the current entry on the fly, and if that entry ever matches a whole word in a line in the first column of your data, then it would send the associated word to your output field.

I made a card with three fields. One is called "output", one is named "theData". In my simple test, field "theData contained a few lines of text, each line containing two words separated by a space.The last field contains this script:

Code: Select all

local tData

on mouseenter
   put fld "theData" into tData
end mouseenter

on keydown var
   put var after me
   if me is  among the words of tData then
      get lineOffset(me,tData)
      put word 2 of line it of tData into fld "output"
   end if
end keydown
When you type into this field, as soon as you complete a word that is in your list, the associated word appears in the "output" field.

You need to set up your own delimiters, and there are probably other little features and caveats, but this should work.

Craig Newman

sturgis
Livecode Opensource Backer
Livecode Opensource Backer
Posts: 1685
Joined: Sat Feb 28, 2009 11:49 pm

Re: Connecting one text field to another

Post by sturgis » Sat Dec 29, 2012 2:32 am

ICCS_User wrote:Where do I locate my data table?
You could use a hidden table field. (or a visible one, hard to know what your end goal is)
You could store the data as a property.
You could create an array as simon did.
You could create the array and then store the array in a property.
You could use a database. (sqlite works well and is fast)

Once its set up, the database would be pretty great but there is some initial learning curve involved in that. Very useful to know of course so it might be worthwhile. Same with arrays. If you haven't dealt with them before you'll have to learn to get your head around some stuff.

Using regular fields (like table fields) is pretty easy but you'll need to understand some things about chunking, like how items, words, lines, chars work in lc, etc.

There is also the datagrid, but if anything it has a harsher learning curve (powerful but can get confusing really fast)

If you decide to go the direction of databases, first I'd get a handle on how things work with straight LC, then once you get proficient, you might consider Andres dblib http://www.andregarzia.com/page/dblib Its payware, but is very good. If you are looking for a more complex (but powerful) solution, sqlYoga is also really well done. I have never really gotten the hang of sqlyoga, but others swear by it. For me dbLib is a better solution. Either is great. Neither is required of course, you can do your own thing with just native lc.


Also just saw the Craig example. Does pretty much the same thing as mine, but is much more concise. Since i'm not positive you are creating a list of matching pairs, or just doing a single search, the Craig method (tm) may be the way to go. Otherwise you will still need loops to process and match up line for line.

ICCS_User
Posts: 12
Joined: Fri Dec 28, 2012 9:06 pm

Re: Connecting one text field to another

Post by ICCS_User » Sat Dec 29, 2012 1:34 pm

Thank you everyone! You guys are amazing! Very helpful stuff that will help me get on the right track.

ICCS_User
Posts: 12
Joined: Fri Dec 28, 2012 9:06 pm

Re: Connecting one text field to another

Post by ICCS_User » Sun Dec 30, 2012 3:57 pm

How do I insure that when a match is being made, it does so for the whole word, not just part. That is, if my list contains both "cheeseburger" and "cheese," and the user types in "cheese" the result is the match for cheese and not cheeseburger.

sturgis
Livecode Opensource Backer
Livecode Opensource Backer
Posts: 1685
Joined: Sat Feb 28, 2009 11:49 pm

Re: Connecting one text field to another

Post by sturgis » Sun Dec 30, 2012 4:34 pm

Using craigs script as an example, you can adjust slightly so that it uses wordoffset rather than lineoffset, set the wholematches to true, and then get the lineindex of that word.
Here is the original script:

Code: Select all

local tData

on mouseenter
   put fld "theData" into tData
end mouseenter

on keydown var
   put var after me
   if me is  among the words of tData then
      get lineOffset(me,tData)
      put word 2 of line it of tData into fld "output"
   end if
end keydown
Here is an adjusted, untested version

Code: Select all

on textchanged 
   if word 1 of me is  among the words of field 1 then
      set the wholematches to true -- force whole word match

-- since lineindex only works with field references, am not using tData
      get the lineindex of word (wordOffset(me,field 1)) of field 1 

-- it now contains the line number of the correct line with the full word match
      put word 2 of line it of field 1 into fld 3 -- grab the word
   else 
      put empty into field 3
   end if
end textchanged

Simon
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 3901
Joined: Sat Mar 24, 2007 2:54 am
Location: Palo Alto

Re: Connecting one text field to another

Post by Simon » Sun Dec 30, 2012 9:51 pm

Hi ICCS,
Just to make sure you can use craig's script, your data should be in this format in fld theData:
Apple Fruit
Banana Fruit
Bandana Clothing
Tomato Vegetable

(Name space Group) look up the "word" keyword
This might be overkill but I thought I'd add it.

Simon
I used to be a newbie but then I learned how to spell teh correctly and now I'm a noob!

ICCS_User
Posts: 12
Joined: Fri Dec 28, 2012 9:06 pm

Re: Connecting one text field to another

Post by ICCS_User » Mon Dec 31, 2012 7:30 pm

Simon wrote:Hi ICCS,
Just to make sure you can use craig's script, your data should be in this format in fld theData:
Apple Fruit
Banana Fruit
Bandana Clothing
Tomato Vegetable

(Name space Group) look up the "word" keyword
This might be overkill but I thought I'd add it.

Simon
This latest change works great! Again, thank you!
One more tweak and I think we'll have it all. Suppose,using your example, the data looks like this:

Apple Fruit
Banana Fruit
Banana Yellow
Banana Peel
Bandana Clothing
Tomato Vegetable

How would I get the output to include all the characteristics associated with Banana. That is, Fruit, Yellow, Peel would all appear in the output field, each on a separate line.

sturgis
Livecode Opensource Backer
Livecode Opensource Backer
Posts: 1685
Joined: Sat Feb 28, 2009 11:49 pm

Re: Connecting one text field to another

Post by sturgis » Mon Dec 31, 2012 9:14 pm

You've now turned the corner to a different problem. To accomplish your task you should probably look at filter.

This is untested, but something like:

Code: Select all

local tData

on mouseenter
   put fld "theData" into tData
end mouseenter

on keydown var
   put var after me 
   put empty into field "output"
   if me is  among the words of tData then
      put tData into tTemp -- put the data into a temp var
      filter tTemp with (me & space & "*") -- filter lines that don't start with your keyword
      repeat for each line tline in tTemp -- loop and place the remaining lines into the output field. 
           put word 2 of tLine & cr after field "output"
      end repeat
      delete the last char of field "output"
   end if
end keydown
At this point though it might be worth it to consider a database solution.

Simon
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 3901
Joined: Sat Mar 24, 2007 2:54 am
Location: Palo Alto

Re: Connecting one text field to another

Post by Simon » Mon Dec 31, 2012 9:33 pm

Hi ICCS,
You almost made me tear my hair out :D
So I'll ask now. Will you want to also do the reverse? Type in "Peel" and get "Banana, Orange, Lemon"?
Well anyways:

Code: Select all

on returnInField
   put "" into fld "output
   put me into tSearch
   put fld theData into tData
   filter tData with tSearch
   if tData <> empty then
      repeat for each line tLine in tData
         put word 2 of tLine & comma & space after fld "output"
      end repeat
   else
      put "Item not found" into fld "output"
   end if
end returnInField
This is not as slick as Craig's script.

Simon EDIT: sturgis beat me to it :D
EDIT2: changed code
Last edited by Simon on Mon Dec 31, 2012 9:53 pm, edited 3 times in total.
I used to be a newbie but then I learned how to spell teh correctly and now I'm a noob!

dunbarx
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 9663
Joined: Wed May 06, 2009 2:28 pm
Location: New York, NY

Re: Connecting one text field to another

Post by dunbarx » Mon Dec 31, 2012 9:34 pm

Hi.

Now you really must look at arrays. But, doing it the old-fashioned way...

I like Sturgis' use of "textChanged" instead of "keyDown", though both work just fine. Long ago, and I mean long ago, I wrote a simple function to find multiple instances of words in text. The function is based on Rinaldi's "fullFind" ( a HC external). Anyway, it will yield a return delimited list of integers, where the first value is the line number of a found word, and the second is the word number within that line (which you do not need). In your example, what this gives you is:

2,1
3,1
4,1

So you can now place this in the entry field script:

Code: Select all

local tData

on mouseenter
   put fld "theData" into tData
end mouseenter

on textchanged 
      if word 1 of me is  among the words of fld "theData"  then
            set the wholematches to true -- force whole word match
      get revFullFind(tData,me,"false")
      repeat for each line tLine in it
         put word 2 of line item 1 of tLine of tData & space after temp
      end repeat
      put me & ":" & temp into fld "output"
      else 
            put empty into field "output"
      end if
end textchanged
And the function is:

Code: Select all

function revFullFind tText,tFind,exactly --RETURNS LINE NUMBER & "," & WORD NUMBER ("EXACTLY " MEANS THE WORD = LINE OR IS MERELY WITHIN THE LINE
   put 0 into counter
   switch exactly
      case "true"
      case empty
         repeat for each line tline in tText
            add 1 to counter
            if tFind = tline then
               put counter & return after tResult
            end if
         end repeat
         break
      case "false"
         repeat for each line tline in tText
            add 1 to counter
            if tFind is in tline then
               repeat with y = 1 to the number of words in tLine
                  if word y of tLine = tFind then put y & "," after temp
               end repeat
               delete last char of temp
               put counter & "," & temp & return after tResult
               put "" into temp
            end if
         end repeat
         break
   end switch
   return tResult
end revFullFind
Are you OK with the somewhat condensed line in the repeat loop? It could be broken into several statements, but try to parse it out.

Again, you have to manage your own delimiters. As many have said, my examples were written with pairs of words in each line, that is, a word, a space, and another word. This was just to play with the example. Your text may be set up differently.

Post Reply

Return to “Getting Started with LiveCode - Complete Beginners”