Data Grid search box (long detailed explination)

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

gricha2380
Posts: 11
Joined: Thu Dec 01, 2011 8:53 pm
Contact:

Data Grid search box (long detailed explination)

Post by gricha2380 » Thu Dec 01, 2011 9:54 pm

Hello LiveCode community,

I have only recently discovered LiveCode while doing a search for a simple cross platform development environment for a class project. Having had experience with Hypercard I was quite happy to learn that this is built on the same paradigms. Here is my current problem:

I am trying to implement a text field as a search box to filter the columns in a Data Grid. Reading through the forum I learned about a useful example in a file called Summer Academy '11 Index. It is exactly the search implementation I was hoping for. Well, kind of. It appears that the Summer Academy Index file populates it's Data Grid from an external text file. I do not need to do this. My Data Grid contains content entered through the Inspector. What I've found as I've tried to use their code in my stack is that upon doing a search my actual content is overridden by their source file. So what I need to do is figure out the necessary code to tell the search to work from the data that's already in the grid and not to reference an external text file.

The Summer Academy stack had search-related code in only two places; the Stack Script and the Script on the search field. In my stack I have copied the code from their search field verbatim because it seems to fit my needs without modification, but the Stack Script has me very confused. I do not understand the LiveCode language well enough (yet) to figure out how to remove the code that searches for the external text file. I need to tell it instead to search based on the that's already in the Data Grid. For the benefit of all of you who are smarter than me, here is the code from the Summer Academy Stack Script:

Code: Select all

global theData

-- SA '11 Index Stack by Mark Smith, Version 1.01 -- July 30, 2011

on preopenstack
   ## Read the Summer Academy Index in from a tab delimited text file into a custom property
   ## this file was created from exporting an Excel file using the tab delimited file option
   ## if this file does not exist on disk it may be in a stack custom property: cindex
   
   put "/users/mark/runrev/summer academy" & "/sa index.txt" into tSavePath
   if there is a file tSavePath then
      -- answer "File found"
      set the dgText of group "DataGrid" to empty -- empty the datagrid control
      put url ("file:" & tSavePath) into theData
      cleanupsaindex  -- cleanup the index
      put false into firstLineContainsColumnNames
    
      set the dgText [ firstLineContainsColumnNames ] of group "DataGrid" to theData
      set the cindex of this stack to theData  -- copy the data into a custom property for later access
      -- i.e. I can distribute the stack with the custom property
   else
      -- answer "File not found"
      put the cindex of this stack into theData  -- copy the custom property into a field
      set the dgText of group "DataGrid" to empty -- empty the datagrid control
      put false into firstLineContainsColumnNames
    
      set the dgText [ firstLineContainsColumnNames ] of group "DataGrid" to theData
   end if
   put the number of lines of thedata into thecount
   put thecount && "records" into fld "count"
end preopenstack

on cleanupsaindex
   -- first, strip leading/trailing quotes from the topic field, excel added these
   set itemdelimiter to tab
   put empty into thecopy -- prepare to copy the data
   repeat for each line tLine in thedata -- thanks mwieder
      put item 1 of tline into ttopic  -- check each topic entry
      put item 2 of tline into tsource
      put item 3 of tline into tlocation
      if ttopic begins with quote then  -- if a leading quote is found
         put char 2 to -2 of ttopic into ttopic -- trim first and last char
      end if
      if ttopic is not empty then
         put ttopic & tab & tsource & tab & tlocation & return after thecopy -- rebuild the line in thecopy
      end if
   end repeat
   put thecopy into thedata  -- copy the filtered version back
   -- here are a couple more cleanup tasks
   replace quote & quote with quote in thedata -- replace double quotes with single quotes
   replace ":30:00" with ":30" in theData -- trimming the hundredths of seconds 
   replace ":00:00" with ":00" in theData -- trimming the hundredths of seconds 
   replace "Ó" with quote in theData  -- replacing wonky trailing quote chars 
   replace "Ò" with quote in theData  -- replace wonky leading quote chars 
end cleanupsaindex


And here is the content from the Summer Academy Search field:

Code: Select all

on rawkeyup
   put fld "search" into tsearch
   put the cindex of this stack into thecopy
   filter thecopy with "*" & tsearch & "*"
   put false into firstLineContainsColumnNames
    
   set the dgText [ firstLineContainsColumnNames ] of group "DataGrid" to thecopy
   put the number of lines in thecopy into thecount
   put thecount && "records" into fld "count"
end rawkeyup

on returninfield
   -- just ignore it
end returninfield
I am certain that for someone experienced in LiveCode it will not take long to identify a potential solution. I am very far from being a programmer, but even still I'm a bit embarrassed to say how long I've spent trying to get this working. :oops:

I hope someone can come to my rescue on this. My wall is beginning to dent from having my head smashed against it so often.

mwieder
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 3581
Joined: Mon Jan 22, 2007 7:36 am
Contact:

Re: Data Grid search box (long detailed explination)

Post by mwieder » Thu Dec 01, 2011 10:39 pm

First off, welcome to the LiveCode community.

I don't have the stack you're referring to, so I'll have to make some guesses here. Caveat: this is untested - make backups and trust no one.

A. If you've gotten this far along I'd hesitate to place you in beginner status. The datagrid is probably the most complex control we have to work with, so kudos if you're not completely flummoxed by now. You've managed to get data into the datagrid to start things off, and that's an accomplishment.

B. I wouldn't do anything in the preOpenStack handler. None of it. Basically, it's reading data from a file or from a custom property of the stack and overriding your built-in and carefully handcrafted data. So either comment out or delete the entire preOpenStack handler.

C. The rawKeyUp handler also sets the datagrid data. I'm not sure why, unless the cindex of the stack changes at some point. But I wouldn't do that either. Try this instead:

Code: Select all

on rawkeyup
   put fld "search" into tsearch
   put the dgText of group "DataGrid" into thecopy
   filter thecopy with "*" & tsearch & "*"
   put the number of lines in thecopy into thecount
   put thecount && "records" into fld "count"
end rawkeyup
and see if that helps.

gricha2380
Posts: 11
Joined: Thu Dec 01, 2011 8:53 pm
Contact:

Re: Data Grid search box (long detailed explination)

Post by gricha2380 » Fri Dec 02, 2011 2:32 am

Mwieder, thank you so very much for your willingness to help.

I inserted the code you wrote, and it definitely made a change. The search box no longer overrides the Data Grid (that's very good), but it actually isn't responding to the search field at all (that's less good, but I know it'll get better). Curiously, the count field is working 100% correctly. As I type in my search, the count field displays the right number of entries in the Data Grid that match my queries, only problem is that the Data Grid itself doesn't update. Could it be because of a setting in Basic Properties of the Data Grid? I turned off Allow Text Editing and turned on everything else.

I have another thought on what could be wrong. I'll attempt to express it in code form, even though I am like a guy trying to fluently speak a language he doesn't understand. I could be completely wrong, but from staring at the Summer Academy code I believe that a line similar to this could send the filtered content of the search into the Data Grid:

Code: Select all

 set the dgText [ firstLineContainsColumnNames ] of group "DataGrid" to thecopy

mwieder
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 3581
Joined: Mon Jan 22, 2007 7:36 am
Contact:

Re: Data Grid search box (long detailed explination)

Post by mwieder » Fri Dec 02, 2011 7:59 am

Oh wait - you want the filtered result to go into the same datagrid the original source text came from?

gricha2380
Posts: 11
Joined: Thu Dec 01, 2011 8:53 pm
Contact:

Re: Data Grid search box (long detailed explination)

Post by gricha2380 » Fri Dec 02, 2011 10:02 am

Yes, I do. Sorry if I caused some confusion. I do want for the filtered results to appear in the Data Grid. The problem has been that the script was clearing out my actual content and filling the grid with data from an outside source. When the user types in the search I'm trying to get the data grid to filter, similar to how iTunes works when you search your library.

mwieder
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 3581
Joined: Mon Jan 22, 2007 7:36 am
Contact:

Re: Data Grid search box (long detailed explination)

Post by mwieder » Fri Dec 02, 2011 7:07 pm

Well... ok. In that case, as you surmised, you'll need one more line in the rawKeyUp handler

Code: Select all

    on rawkeyup
       put fld "search" into tsearch
       put the dgText of group "DataGrid" into thecopy
       filter thecopy with "*" & tsearch & "*"
       -- taking a shortcut here to set the data back into the datagrid
       set the dgText [false] of group "DataGrid" to thecopy
       put the number of lines in thecopy into thecount
       put thecount && "records" into fld "count"
    end rawkeyup
...but doesn't that defeat the purpose of having put the data in the datagrid via the property inspector in the first place? It's gone after you do this. What are you trying to accomplish here?

gricha2380
Posts: 11
Joined: Thu Dec 01, 2011 8:53 pm
Contact:

Re: Data Grid search box (long detailed explination)

Post by gricha2380 » Fri Dec 02, 2011 9:06 pm

I see what you mean. That's a problem I didn't really expect. Is there a way to take the original content of the Data Grid and store it in a variable at the very beginning of the process so that when the search field is cleared all the content will become visible again? In my head I assumed that it would automatically work that way by default. Maybe that was wishful thinking. :oops:

gricha2380
Posts: 11
Joined: Thu Dec 01, 2011 8:53 pm
Contact:

Re: Data Grid search box (long detailed explination)

Post by gricha2380 » Fri Dec 02, 2011 9:24 pm

I can't figure out how they're doing it, but the Summer Academy Index is doing it in their stack. Once the search field is cleared their list returns to what it was before. Would it help if I get you a link to that file, or can you determine what's going on from the code I've already posted?

mwieder
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 3581
Joined: Mon Jan 22, 2007 7:36 am
Contact:

Re: Data Grid search box (long detailed explination)

Post by mwieder » Fri Dec 02, 2011 9:54 pm

Yeah - probably the easiest way would be to store it in a custom property and just grab it from there. That's what the original sample is doing after loading it from a file. So something like this:

Code: Select all

        on preOpenStack
           -- stash away the original datagrid text so we don't lose track of it
           set the uVirginText of group "Datagrid" to the dgText of group "Datagrid"
        end preOpenStack

        on closeStack
           -- restore the datagrid text for our next session
           set the dgText of group "Datagrid" to the uVirginText of group "Datagrid"
        end closeStack

Code: Select all

        on rawkeyup
           put fld "search" into tsearch
           -- get the original text from the custom property
           put the uVirginText of group "DataGrid" into thecopy
           filter thecopy with "*" & tsearch & "*"
           -- taking a shortcut here to set the data back into the datagrid
           set the dgText [false] of group "DataGrid" to thecopy
           put the number of lines in thecopy into thecount
           put thecount && "records" into fld "count"
        end rawkeyup

gricha2380
Posts: 11
Joined: Thu Dec 01, 2011 8:53 pm
Contact:

Re: Data Grid search box (long detailed explination)

Post by gricha2380 » Fri Dec 02, 2011 11:08 pm

It's so close I can taste it! Your solution has brought it to 99% completion. The Data Grid filtering is working, but there is a strange problem. There is a double-layering bug in the grid's text content. It's difficult to describe without a picture, but I'll try:

It seems that there are two layers of text within each row of the Data Grid. The two layers are stacked on each other, giving all the content a very bold appearance, sort of like super bad anti-ailasing. The reason I know that it's stacking two layers of text is because when I type into the search box, the content of the Data Grid gets jumbled. What happens is that only one layer of text is being filtered (in other words, it disappears when it does not match my search query--exactly what it's suppose to do), but one layer of text remains behind no matter what I search for. So, for example, if my search gives only one result, I see the top line of the Data Grid as a jumbled entry (two different sentences written on top of each other), and the rest of the table is still filled with content (clearly readable content with no bold appearance, because the top layer that was previously distorting it has been filtered by my search).

I would really like to get your a picture, or even send you my stack to make the issue clearer (slight pun intended). Please let me know if you want me to do that.

I am unsure if this is a general bug with DataGrids. I have been probing around but I haven't found any mentions of this particular problem on the forum. You are my Jedi mentor, please advise me on how to proceed!

mwieder
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 3581
Joined: Mon Jan 22, 2007 7:36 am
Contact:

Re: Data Grid search box (long detailed explination)

Post by mwieder » Fri Dec 02, 2011 11:40 pm

OK - I'm gonna take a wild guess at this because I can't test this out right now and don't have it in front of me - it sounds from your description like the rows of the datagrid are getting overwritten properly *only* when there's actual data to overwrite, and otherwise your original content is still there. So how about something like

Code: Select all

set the dgText of group "Datagrid" to empty
at the start of the rawKeyUp handler?

gricha2380
Posts: 11
Joined: Thu Dec 01, 2011 8:53 pm
Contact:

Re: Data Grid search box (long detailed explination)

Post by gricha2380 » Sat Dec 03, 2011 12:07 am

Same result so far. I'll experiment with placing that code in different places...

gricha2380
Posts: 11
Joined: Thu Dec 01, 2011 8:53 pm
Contact:

Re: Data Grid search box (long detailed explination)

Post by gricha2380 » Sat Dec 03, 2011 4:44 am

it sounds from your description like the rows of the datagrid are getting overwritten properly *only* when there's actual data to overwrite, and otherwise your original content is still there.
Take a look. The table on the left is what I see just by opening the card. The table on the right is a duplicate table that is not tied into the search code.

img542.imageshack.us/img542/4213/screenshot20111202at102.png

When I actually do a search the table content becomes even more distorted.
img580.imageshack.us/img580/4213/screenshot20111202at102.png

marksmithhfx
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 931
Joined: Thu Nov 13, 2008 6:48 am

Re: Data Grid search box (long detailed explination)

Post by marksmithhfx » Sat Dec 03, 2011 9:54 am

mwieder wrote:Yeah - probably the easiest way would be to store it in a custom property and just grab it from there. That's what the original sample is doing after loading it from a file. So something like this:

Code: Select all

        on preOpenStack
           -- stash away the original datagrid text so we don't lose track of it
           set the uVirginText of group "Datagrid" to the dgText of group "Datagrid"
        end preOpenStack

        on closeStack
           -- restore the datagrid text for our next session
           set the dgText of group "Datagrid" to the uVirginText of group "Datagrid"
        end closeStack
I wonder if you are possibly putting multiple copies of the data into the datagrid? I noticed I always cleared the datagrid before reloading it with a fresh copy. That might just be superstitious behaviour on my part (I am pretty new to this as well) but perhaps worth a try (you'll have to figure out a way to get just 1 copy of the data into uVirginText to start the process off with):

Code: Select all

        on closeStack
           -- restore the datagrid text for our next session
           set the dgText of group "Datagrid" to empty
           set the dgText of group "Datagrid" to the uVirginText of group "Datagrid"
        end closeStack
Last edited by marksmithhfx on Sat Dec 03, 2011 4:12 pm, edited 1 time in total.
macOS 12.6.5 (Monterey), Xcode 14.2, LC 10.0.0, iOS 15.6.1
Targets: Mac, iOS

marksmithhfx
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 931
Joined: Thu Nov 13, 2008 6:48 am

Re: Data Grid search box (long detailed explination)

Post by marksmithhfx » Sat Dec 03, 2011 10:20 am

After re-reading this thread I will make a couple of comments to hopefully clear up some confusion. If you ignore the fact that I have to cleanup the data I am importing from the external file then, all the preopenstack handler is doing is initializing the datagrid with the contents of a file and then storing it in a custom property (cindex) for later use. When I distributed the stack I did not distribute the external file, so the "else" clause just initializes the datagrid from the custom property (cindex). Storing the data in a custom property instead of a variable just meant it was persistent across executions of the program/stack.

In the search field I always start by filtering a "copy" of cindex and then putting that into the datagrid (interestingly I just noticed I never clear out the datagrid before putting the filtered data into it... there must be a reason, I've just forgotten what it is).

Gricha2380, if there is anything else in there that is still confusing just let me know and I'll try and provide an explanation. PS I am glad to see the stack was a useful starting point for you (and thanks to Mark Wieder for providing you with such excellent mentorship... he has helped me out on many occasions as well).

Cheers,

-- Mark
macOS 12.6.5 (Monterey), Xcode 14.2, LC 10.0.0, iOS 15.6.1
Targets: Mac, iOS

Post Reply