- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Get Direct Link
- Report Inappropriate Content
Searching elements in listbox
I would like to know if there is an easy way to find elements in GUI having a Listbox.
Something like the column search filter but for a Listbox.
Accepted Solutions
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Get Direct Link
- Report Inappropriate Content
Re: Searching elements in listbox
This solution will update the listbox with every character you type. First shown to me by Justin Chilton.
filter_items = Function( {this, searchText},
{filtered_items, i},
// only attempt to filter if there is any text
If( searchText != "",
// new list for groups that match searchText
filtered_items = {};
// Check if each group matches the given text
For( i = 1, i <= N Items( item_list ), i++,
// Insert to our list if it contains our search text (case insensitive)
If( Contains( Lowercase( item_list[i] ), Lowercase( searchText ) ),
Insert Into( filtered_items, item_list[i] );
)
);
,
// else show all groups
filtered_items = item_list;
);
item_disp_box << Set Items( filtered_items );
); // end filter_items function
item_list = {"Alabama", "Alaska", "Arizona", "Arkansas", "California", "Colorado", "Connecticut", "Delaware", "Florida",
"Georgia", "Hawaii", "Idaho", "Illinois", "Indiana", "Iowa", "Kansas", "Kentucky", "Louisiana", "Maine",
"Maryland", "Massachusetts", "Michigan", "Minnesota", "Mississippi", "Missouri", "Montana", "Nebraska",
"Nevada", "New Hampshire", "New Jersey", "New Mexico", "New York", "North Carolina", "North Dakota", "Ohio",
"Oklahoma", "Oregon", "Pennsylvania", "Rhode Island", "South Carolina", "South Dakota", "Tennessee", "Texas",
"Utah", "Vermont", "Virginia", "Washington", "West Virginia", "Wisconsin", "Wyoming"};
nw = new window("Demonstrate Listbox Search",
hlistbox(
icon box("SearchIndex"),
spacer box(size(5, 10)),
item_search_teb = text edit box("",
<< set width(300),
// The filter_items function does the work
<< set text changed(filter_items)),
reset_button = button box("",
<< set icon("DebuggerDeleteBreakpoint"),
<< set script(
// Clear the filter and call the callback function
item_search_teb << set text("");
filter_items(item_search_teb, "");
),
<< set tip("Clear filter"),
),
),
panelbox("Select a state:",
item_disp_box = listbox(item_list, width(200), nlines(10)),
),
)
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Get Direct Link
- Report Inappropriate Content
Re: Searching elements in listbox
Here is a simple example of a search in a List Box().
Names Default To Here( 1 );
New Window( "Example",
fontobj = lb = List Box(
{"First Item", "Second Item", "Third Item"},
width( 200 ),
max selected( 2 ),
nlines( 6 )
)
);
show(contains(lb<<get items,"Second Item"))
If you can provide more details, a more exacting answer may be available
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Get Direct Link
- Report Inappropriate Content
Re: Searching elements in listbox
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Get Direct Link
- Report Inappropriate Content
Re: Searching elements in listbox
Building on @txnelson thoughts:
NamesDefaultToHere(1);
lbi = {"First Item", "Second Item", "Second Item Duplicate", "Third Item"};
New Window( "Searchable List Box",
PanelBox("Type in the box below and hit Enter to select matching list items",
teb = TextEditBox("", << setScript(updateLB), << setWidth(200)),
lb = List Box(lbi, << setWidth(200))
)
);
updateLB =
Expr(
txt = teb << getText;
lbiNew = lbi;
if(txt != "",
// Remove non-matching items according to some logic
for(i = NItems(lbi), i>= 1, i--, if(!StartsWith(lbi[i], txt), RemoveFrom(lbiNew, i)));
);
// Set new items
lb << setItems(lbiNew);
);
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Get Direct Link
- Report Inappropriate Content
Re: Searching elements in listbox
This solution will update the listbox with every character you type. First shown to me by Justin Chilton.
filter_items = Function( {this, searchText},
{filtered_items, i},
// only attempt to filter if there is any text
If( searchText != "",
// new list for groups that match searchText
filtered_items = {};
// Check if each group matches the given text
For( i = 1, i <= N Items( item_list ), i++,
// Insert to our list if it contains our search text (case insensitive)
If( Contains( Lowercase( item_list[i] ), Lowercase( searchText ) ),
Insert Into( filtered_items, item_list[i] );
)
);
,
// else show all groups
filtered_items = item_list;
);
item_disp_box << Set Items( filtered_items );
); // end filter_items function
item_list = {"Alabama", "Alaska", "Arizona", "Arkansas", "California", "Colorado", "Connecticut", "Delaware", "Florida",
"Georgia", "Hawaii", "Idaho", "Illinois", "Indiana", "Iowa", "Kansas", "Kentucky", "Louisiana", "Maine",
"Maryland", "Massachusetts", "Michigan", "Minnesota", "Mississippi", "Missouri", "Montana", "Nebraska",
"Nevada", "New Hampshire", "New Jersey", "New Mexico", "New York", "North Carolina", "North Dakota", "Ohio",
"Oklahoma", "Oregon", "Pennsylvania", "Rhode Island", "South Carolina", "South Dakota", "Tennessee", "Texas",
"Utah", "Vermont", "Virginia", "Washington", "West Virginia", "Wisconsin", "Wyoming"};
nw = new window("Demonstrate Listbox Search",
hlistbox(
icon box("SearchIndex"),
spacer box(size(5, 10)),
item_search_teb = text edit box("",
<< set width(300),
// The filter_items function does the work
<< set text changed(filter_items)),
reset_button = button box("",
<< set icon("DebuggerDeleteBreakpoint"),
<< set script(
// Clear the filter and call the callback function
item_search_teb << set text("");
filter_items(item_search_teb, "");
),
<< set tip("Clear filter"),
),
),
panelbox("Select a state:",
item_disp_box = listbox(item_list, width(200), nlines(10)),
),
)
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Get Direct Link
- Report Inappropriate Content
Re: Searching elements in listbox
Nice! I didn't know about '' << setTextChanged()'.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Get Direct Link
- Report Inappropriate Content
Re: Searching elements in listbox
Hello, thanks for the solution but it doesn't work when we have several listboxes in the same window. Could you please help me ? I would like to have a generic function to replace listbox() native function with such a filter. I tried with {DefaultLocal} into my function, but it doesn't work. I would like to add an argument to the filter_items() function but I can't. Where am I wrong ?
filter_items = Function( {this, searchText},
{filtered_items, i},
// only attempt to filter if there is any text
If( searchText != "",
// new list for groups that match searchText
filtered_items = {};
// Check if each group matches the given text
For( i = 1, i <= N Items( item_list ), i++,
// Insert to our list if it contains our search text (case insensitive)
If( Contains( Lowercase( item_list[i] ), Lowercase( searchText ) ),
Insert Into( filtered_items, item_list[i] );
)
);
,
// else show all groups
filtered_items = item_list;
);
item_disp_box << Set Items( filtered_items );
); // end filter_items function
listbox_with_filter = Function( {item},
listbox =
vlistbox(
hlistbox(
icon box("SearchIndex"),
spacer box(size(5, 10)),
item_search_teb =
text edit box("",
<< set width(300),
// The filter_items function does the work
<< set text changed(filter_items )
),
reset_button =
button box("",
<< set icon("DebuggerDeleteBreakpoint"),
<< set script(
// Clear the filter and call the callback function
item_search_teb << set text("");
filter_items(item_search_teb, "");
),
<< set tip("Clear filter"),
),
),
panelbox("Select a state:",
item_disp_box = listbox(item, width(200), nlines(10)),
)
);
return( listbox );
);
item_list1 = {"Alabama", "Alaska", "Arizona", "Arkansas", "California", "Colorado", "Connecticut", "Delaware", "Florida",
"Georgia", "Hawaii", "Idaho", "Illinois", "Indiana", "Iowa", "Kansas", "Kentucky", "Louisiana", "Maine",
"Maryland", "Massachusetts", "Michigan", "Minnesota"};
item_list2 = {"Mississippi", "Missouri", "Montana", "Nebraska",
"Nevada", "New Hampshire", "New Jersey", "New Mexico", "New York", "North Carolina", "North Dakota", "Ohio",
"Oklahoma", "Oregon", "Pennsylvania", "Rhode Island", "South Carolina", "South Dakota", "Tennessee", "Texas",
"Utah", "Vermont", "Virginia", "Washington", "West Virginia", "Wisconsin", "Wyoming"};
nw = new window("Two Listbox Search",
HListBox(
listbox_with_filter( item_list1 )
,
listbox_with_filter( item_list2 )
)
);
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Get Direct Link
- Report Inappropriate Content
Re: Searching elements in listbox
How I build these changes case by case, but using Filter Col Selector is fairly simple (usually I don't have to worry about the private tables, but I don't know your use case, so I did some trickery for them)
Names Default To Here(1);
create_filter = function({items}, {Default Local},
dt = New Table("",
New Column("a", Character, Values(items)),
private
);
dt_split = dt << Split(
Split By(:a),
Split(:a),
Output Table("temp"),
Sort by Column Property,
private
);
Close(dt, no save);
Eval(EvalExpr(
fcs = Filter Col Selector(dt_split, << Set Script(
Expr(dt_split); // not sure how robust this will be, used to store the private table reference
));
));
return(fcs);
);
item_list1 = {"Alabama", "Alaska", "Arizona", "Arkansas", "California", "Colorado", "Connecticut", "Delaware", "Florida",
"Georgia", "Hawaii", "Idaho", "Illinois", "Indiana", "Iowa", "Kansas", "Kentucky", "Louisiana", "Maine",
"Maryland", "Massachusetts", "Michigan", "Minnesota"};
item_list2 = {"Mississippi", "Missouri", "Montana", "Nebraska",
"Nevada", "New Hampshire", "New Jersey", "New Mexico", "New York", "North Carolina", "North Dakota", "Ohio",
"Oklahoma", "Oregon", "Pennsylvania", "Rhode Island", "South Carolina", "South Dakota", "Tennessee", "Texas",
"Utah", "Vermont", "Virginia", "Washington", "West Virginia", "Wisconsin", "Wyoming"};
nw = New Window("demo",
H List Box(
a = create_filter(item_list1),
b = create_filter(item_list2)
)
);
You can also use V List Box and build it using Text Edit Box (you want to store the original list somewhere)
Names Default To Here(1);
create_filter = function({items}, {Default Local},
Eval(EvalExpr(
vlb = V List Box(
Text Edit Box("", <<Set Text Changed(Function({this, value},
all_items = Expr(items);
new_list = Filter Each({name}, all_items, Contains(lowercase(name), lowercase(value)));
If(N Items(new_list) == 0 & IsMissing(value),
new_list = all_items;
);
(this << sib) << set items(new_list)
))),
List Box(items)
);
));
return(vlb);
);
item_list1 = {"Alabama", "Alaska", "Arizona", "Arkansas", "California", "Colorado", "Connecticut", "Delaware", "Florida",
"Georgia", "Hawaii", "Idaho", "Illinois", "Indiana", "Iowa", "Kansas", "Kentucky", "Louisiana", "Maine",
"Maryland", "Massachusetts", "Michigan", "Minnesota"};
item_list2 = {"Mississippi", "Missouri", "Montana", "Nebraska",
"Nevada", "New Hampshire", "New Jersey", "New Mexico", "New York", "North Carolina", "North Dakota", "Ohio",
"Oklahoma", "Oregon", "Pennsylvania", "Rhode Island", "South Carolina", "South Dakota", "Tennessee", "Texas",
"Utah", "Vermont", "Virginia", "Washington", "West Virginia", "Wisconsin", "Wyoming"};
nw = New Window("demo",
H List Box(
vlb1 = create_filter(item_list1),
vlb2 = create_filter(item_list2)
)
);
and there are also other methods depending on the application and use case.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Get Direct Link
- Report Inappropriate Content
Re: Searching elements in listbox
With a Combo Box you can combine both feature in one Display Box - a freely editable text edit box and a list which is linked to it:
suggestions={"some","values","to","pick"};
new window("test", cb = Combo Box( suggestions, editable,<<Set Width( 300 ) ))
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Get Direct Link
- Report Inappropriate Content
Re: Searching elements in listbox
Thank you very much for the two solutions !
I prefer the one with texteditbox because when we have lots of listboxes, I am afraid about the high number of private tables that won't be closed (memory charge).
Thanks a lot it's perfect for me the second solution;
Carole