Client-side RadListBox Filter

4 posts, 0 answers
  1. Jon Shipman
    Jon Shipman avatar
    43 posts
    Member since:
    Nov 2009

    Posted 27 Oct 2010 Link to this post

    Requirements

    RadControls version v.2010.2.929.35

    .NET version 3.5 

    Visual Studio version 2008

    programming language N/A

    browser support

    all browsers supported by RadControls


    PROJECT DESCRIPTION

    Combine RadComboBox-like Filtering with a RadListBox.

    I'm using a RadListBox that can contain several hundred RadListBoxItems.  Once my user locates the desired item, they need to "assign" it to another object by dragging it to a node in a RadTreeView.

    Because there are so many items in my RadListBox, it can be cumbersome for the user to locate the desired item.

    I wanted to combine the filtering functionality of the RadComboBox with the drag and drop functionality of the RadListBox.

    In this "starter" project I set up a text box above the RadListBox that will filter the items much like the RadComboBox.  The RadListIems can be dragged from the left box to the right box.

    Here's a video demo of the usage I implemented.

    To run the project, 

    *Notes:

    This is all the functionality I needed for my project, so I had to post what I had and get back to my work.  You know what I mean...  So here are some notes in case you decide to use my example project as a starting point.

    Transfer Button Functionality is not complete: I just needed drag and drop.  If you use the transfer buttons instead of drag and drop, you'll need to write some more code to handle your situation.  For instance, transfer "all" will transfer hidden items as well.  Highlighted matching text will remain highlighted if you use the buttons.

    Up and Down Arrow Usage: If the user uses the up and down arrows to go through a filtered list, it may appear to not work because the up and down arrow will potentially be "stopping" on hidden items.  I've asked the Telerik folks if I could override this and noted that perhaps the default behavior should be to only stop on visible items.

    As a user, I want to use the down arrow as soon as I see my match.  I started to implement the functionality where the down arrow set the focus on the RadListBox, but due to the above issue with hidden items, I'm holding off on that implementation for now.

    Special Character Matching: If you have "special" characters in your RadListBoxItems that you are trying to match, I wish you much luck. :-)  Certain characters are automatically rendered by the RadListBox using their HTML entity equivalent.  These items won't be matched.

    Also, if you actually have items in your list that will affect a Regular Expression, such as '^', the matching behavior will become unpredictable.  In my example, it will not cause an error if the user enters a special character in the filter, but if there is a match for the special character in a RadListBoxItem, it may not match as expected.

    You may want to use a RadTextBox to avoid certain characters.

    Hope this helps someone get started!

    CSS:
    div.notes
    {
        color: Red;
        font-family: "Segoe UI", Arial;
        margin-bottom: 20px;
    }
    .RadListBox span.rlbText em
    {
        background-color: #E5E5E5;
        font-weight: bold;
        font-style: normal;
    }

    JavaScript:
    var listbox;
    var filterTextBox;
     
    function pageLoad()
    {
        listbox = $find("<%= RadListBox1.ClientID %>");
        filterTextBox = document.getElementById("<%= TextBox1.ClientID %>");
        // set on anything but text box
        listbox._getGroupElement().focus();
    }
     
    function OnClientDroppedHandler(sender, eventArgs)
    {
        // clear emphasis from matching characters
        eventArgs.get_sourceItem().set_text(clearTextEmphasis(eventArgs.get_sourceItem().get_text()));
    }
     
    function filterList()
    {
        clearListEmphasis();
        createMatchingList();
    }
     
    // clear emphasis from matching characters for entire list
    function clearListEmphasis()
    {
        var re = new RegExp("</{0,1}em>", "gi");
        var items = listbox.get_items();
        var itemText;
     
        items.forEach
        (
            function(item)
            {
                itemText = item.get_text();
                item.set_text(clearTextEmphasis(itemText));
            }
        )
    }
     
    // clear emphasis from matching characters for given text
    function clearTextEmphasis(text)
    {
        var re = new RegExp("</{0,1}em>", "gi");
        return text.replace(re, "");
    }
     
    // hide listboxitems without matching characters
    function createMatchingList()
    {
        var items = listbox.get_items();
        var filterText = filterTextBox.value;
        var re = new RegExp(filterText, "i");
     
        items.forEach
        (
            function(item)
            {
                var itemText = item.get_text();
     
                if (itemText.toLowerCase().indexOf(filterText.toLowerCase()) != -1)
                {
                    item.set_text(itemText.replace(re, "<em>" + itemText.match(re) + "</em>"));
                    item.set_visible(true);
                }
                else
                {
                    item.set_visible(false);
                }
            }
        )
    }

    ASP.NET Markup:
    <telerik:RadScriptManager ID="RadScriptManager1"
        runat="server">
    </telerik:RadScriptManager>
    <div class="notes">
        See the "*Notes" section in the posting.
    </div>
    <div>
        <asp:TextBox ID="TextBox1"
            runat="server"
            Width="165px"
            onkeyup="filterList();" />
    </div>
    <br />
    <div>
        <telerik:RadListBox ID="RadListBox1"
            runat="server"
            Width="200px"
            Height="200px"
            AllowTransfer="true"
            TransferToID="RadListBox2"
            EnableDragAndDrop="true"
            OnClientDropped="OnClientDroppedHandler">
            <Items>
                <telerik:RadListBoxItem
                    Text="Kansas"
                    Value="KS" />
                <telerik:RadListBoxItem
                    Text="Texas"
                    Value="TX" />
                <telerik:RadListBoxItem
                    Text="Missouri"
                    Value="MO" />
                <telerik:RadListBoxItem
                    Text="Oklahoma"
                    Value="OK" />
                <telerik:RadListBoxItem
                    Text="Arizona"
                    Value="AZ" />
                <telerik:RadListBoxItem
                    Text="South Dakota"
                    Value="SD" />
                <telerik:RadListBoxItem
                    Text="Colorado"
                    Value="CO" />
                <telerik:RadListBoxItem
                    Text="New Mexico"
                    Value="NM" />
                <telerik:RadListBoxItem
                    Text="Iowa"
                    Value="IA" />
                <telerik:RadListBoxItem
                    Text="Nebraska"
                    Value="NE" />
                <telerik:RadListBoxItem
                    Text="Illinois"
                    Value="IL" />
                <telerik:RadListBoxItem
                    Text="Kentucky"
                    Value="KY" />
            </Items>
        </telerik:RadListBox>
        <telerik:RadListBox ID="RadListBox2"
            runat="server"
            Width="200px"
            Height="200px"
            EnableDragAndDrop="false">
        </telerik:RadListBox>
    </div>
    <telerik:RadInputManager ID="RadInputManager1" runat="server">
        <telerik:TextBoxSetting
            BehaviorID="TextBoxBehavior1"
            EmptyMessage="search states...">
            <TargetControls>
                <telerik:TargetInput ControlID="TextBox1" />
            </TargetControls>
        </telerik:TextBoxSetting>
    </telerik:RadInputManager>
  2. Will
    Will avatar
    1 posts
    Member since:
    Aug 2011

    Posted 19 Aug 2011 Link to this post

    Jon,
    Very cool!  I'm ok at .net development but when it comes to client-side javascript, etc. I know very little.  Any chance you would finish this to support the buttons, etc and post it?  It would be very useful.  

    side note:I find that if I put an additional button on the page say "Button99" with your sample.... that using the > or < buttons after a search is performed causes the "Button99" to no longer respond or fire an event or sometimes does this:

    A potentially dangerous Request.Form value was detected from the client (RadListBox2_ClientState="...","text":"<em>K</em>ansas","vi...").


    Any time or thought you put into this would be much appreciated.
    Thanks,
    Will
  3. Jon Shipman
    Jon Shipman avatar
    43 posts
    Member since:
    Nov 2009

    Posted 22 Aug 2011 Link to this post

    Hey Will,

    I've got a pretty hefty work load this week, but I have done some more work with this and I should be able to update it next week sometime.
  4. Jon Shipman
    Jon Shipman avatar
    43 posts
    Member since:
    Nov 2009

    Posted 18 Oct 2011 Link to this post

    I finally got around to updating the project.  I changed several things, so I posted a new project here.

    On the error you were getting, I went ahead and wrote code in the new project to clear the <em> tags from the item after it's transferred.

    Also, I consider that error a "reminder" from the .NET developers to make sure you're handling potentially malicious inputs.  After you've written code to handle inputs, you can turn off that reminder by setting the validateRequest attribute to false in the pages node inside the system.web node:

    <pages validateRequest="false"></pages>


    One last note on that.  Here's my understanding on a related situation.  I converted a project to .NET 4.0 and started getting the following exception:

    Sys.WebForms.PageRequestManagerServerErrorException


    Prior to .NET 4.0 only aspx page requests were validated.  In .NET 4.0 they switched to validating all requests, including the custom httpHandlers Telerik uses.  So even with validateRequest set to "false", I was getting the "potentially dangerous..." exception, but it was bubbling up as the above exception.

    If you've appropriately handled the potentially dangerous input, and you're using .NET 4.0, add the following in the sys.web node in the web.config and it should prevent the issue.

    <httpRuntime requestValidationMode="2.0" />
Back to Top