Click here to Skip to main content
11,578,739 members (65,390 online)
Click here to Skip to main content

See search results as you type - An ASP.NET AJAX control

, 11 Apr 2008 CPOL 80.4K 6.8K 66
Rate this:
Please Sign up or sign in to vote.
A search box that updates the page with search results as you type.

DelayedSubmitDemo

Introduction

Highrise and other new AJAX enabled tools have this feature that when you type in a search query, it automatically updates the search results below. It's almost like an auto-complete box, but with the full results on the page instead of a dropdown list below the control. Unfortunately, I didn't find anything like this in the Microsoft ASP.NET AJAX Toolkit. So, I decided that this was a good way to finally dive into the AJAX Control Toolkit.

Here is the result: Live Demo.

It's my first AJAX control, so I'm sure there is room for improvements. I've tested it in IE7, FF, and Safari. Seems to work fine in all of them.

Background

I used the Membership Editor Example from Peter Keller and TextChangedBehavior.js from Garbin as my inspiration and resource, but started with a VS ASP.NET AJAX Control Project to get the framework up and running.

The Use Case

The user starts typing his search query into the textbox. After he types in the first few characters of the keyword he is looking for, he pauses. Magically, all search results that fit his query so far appear below. If he types in more of the keyword, the results are updated accordingly.

Example: A user is seaching for a contact. He types Bl and stops. The names that now show up could include:

  • Blaettler
  • Blatt
  • Blackmore
  • Bloomfield
  • Blodgett
  • Blum

Now, he types another letter, let's say, o, and the list reduces itself to:

  • Bloomfield
  • Blodgett

The Control

There is really only JavaScript code that has functionality. The only thing the code does is start a time on the keyup event, stop the time on keydown, and after the timer fires, it executes the onchange method of the associated TextBox. This way, we get a delayed postback after the user stops typing and not lots of postbacks when he's still writing something.

_onkeyup : function(ev) {
    var k = ev.keyCode ? ev.keyCode :
                ev.rawEvent.keyCode;
    if (k != Sys.UI.Key.Tab) {
        this._timer.set_enabled(true);
    }
},

_onkeydown : function(ev) {
    this._timer.set_enabled(false);
},

_onTimerTick : function(sender, eventArgs) {
    this._timer.set_enabled(false);

    if(this._text != this.get_element().value) {
        this._text = this.get_element().value;

        this.get_element().onchange();
    }
},

Everything else is just setup and teardown code. There is one property in the C# file called Timeout. This determines how long of a pause the user needs to make until the search results get updated.

Using the Code

Just add this control like any other Extender to your ASPX page, set the TargetControlID, and add a TextChanged handler to the search textbox.

<cc1:DelayedSubmitExtender 
    ID="DisableButtonExtender1" 
    runat="server" 
    Timeout="1000" 
    TargetControlID="TextBox1"/>
<asp:TextBox 
    ID="TextBox1" 
    runat="server" 
    AutoPostBack="True" 
    OnTextChanged="TextBox1_TextChanged" 
    Columns="50"></asp:TextBox>        
<br />
List of matching words:<br />

<asp:UpdatePanel ID="UpdatePanel1" runat="server">
    <Triggers>
        <asp:AsyncPostBackTrigger ControlID="TextBox1" />
    </Triggers>
    <ContentTemplate>
        <asp:Repeater ID="Repeater1" runat="server">
            <HeaderTemplate><ul></HeaderTemplate>
            <ItemTemplate>
                <li><%#DataBinder.Eval(Container, "DataItem[0]")%></li>
            </ItemTemplate>
            <FooterTemplate></ul></FooterTemplate>
        </asp:Repeater>
    </ContentTemplate>
</asp:UpdatePanel>

I would then wrap the search results area in an UpdatePanel. If the TextBox is outside, just add an AsyncPostBackTrigger to the UpdatePanel. Inside the UpdatePanel, you can present your search results. For my example, I just have a list of words.

Code-behind

protected void TextBox1_TextChanged(object sender, EventArgs e)
{
    List<string[] /> items = new List<string[] />();

    for (int i = 0; i < wordlist.Length; i++ )
    {
        if (wordlist[i].StartsWith(
                TextBox1.Text, 
                StringComparison.OrdinalIgnoreCase))
        {
            string[] item = new string[1];
            item[0] = wordlist[i];

            items.Add(item);
        }
    }

    Repeater1.DataSource = items;
    Repeater1.DataBind();
}

In the TextChanged handler on the server side, you need to add your specific search code. As mentioned above, I just display a list of words with a Repeater control. The list is contained in a string array called wordlist.

I would recommend to just have a look at the example. It's very simple, and should show you how this works.

Please let me know how it works and if it is of any use. Good luck!

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Remy Blaettler
Web Developer
United States United States
Remy Blaettler (or Rémy Blättler in Swiss German writing) works as the Chief of the System for Supertext AG.

Supertext is the first online copywriting agency and has over 300 professional freelance writers, journalists, proofreaders and translaters in ints network.


Remy started dabbling with Computers when he was 12 on his fathers 286 PC with Basic, he soon moved to Turbo Pascal and then to C++. The last 3 years were dedicated to C# and some ASP.NET.

You may also be interested in...

Comments and Discussions

 
GeneralMy vote of 3 Pin
Member 1039649318-Sep-14 0:12
memberMember 1039649318-Sep-14 0:12 
GeneralMy vote of 2 Pin
dareen_15-May-14 10:54
memberdareen_15-May-14 10:54 
QuestionGood Pin
WassimSaasouh10-Oct-13 21:34
memberWassimSaasouh10-Oct-13 21:34 
QuestionNew Version? Pin
slavisam30-Sep-13 5:42
memberslavisam30-Sep-13 5:42 
Questionits good Pin
KhanFaiz17-Aug-12 21:53
memberKhanFaiz17-Aug-12 21:53 
AnswerRe: its good Pin
Remy Blaettler19-Aug-12 22:53
memberRemy Blaettler19-Aug-12 22:53 
QuestionGood article... Pin
Midhunlal G26-Jun-12 23:51
memberMidhunlal G26-Jun-12 23:51 
AnswerRe: Good article... Pin
Remy Blaettler27-Jun-12 2:49
memberRemy Blaettler27-Jun-12 2:49 
Hmm, what browser do you use?

I have a bit an updated Javascript, maybe that helps:


Type.registerNamespace('DelayedSubmit');
 
DelayedSubmit.DelayedSubmitBehavior = function(element) {
 
    DelayedSubmit.DelayedSubmitBehavior.initializeBase(this, [element]);
 
    this._text = null;
    this._timer = null;
    this._tickHandler = null;
    this._keyupHandler = null;
    this._keydownHandler = null;
 
    this._changeHandler = null;
 
    this._TimeoutValue = null;
 
}
 
DelayedSubmit.DelayedSubmitBehavior.prototype = {
 
    initialize : function() {
        DelayedSubmit.DelayedSubmitBehavior.callBaseMethod(this, 'initialize');
 
        this._tickHandler = Function.createDelegate(this, this._onTimerTick);
        
        this._timer = new Sys.Timer();
        this._timer.set_interval(this._TimeoutValue);
        this._timer.add_tick(this._tickHandler);
               
        this._keyupHandler = Function.createDelegate(this, this._onkeyup);
        $addHandler(this.get_element(), "keyup", this._keyupHandler);    
        
        this._keydownHandler = Function.createDelegate(this, this._onkeydown);
        $addHandler(this.get_element(), "keydown", this._keydownHandler);
        
        //remove the original onchange handler, in firefox it gets fired even if we overwrite the keyup/keydown handler
        this._changeHandler = this.get_element().onchange;        
        this.get_element().onchange = null;
    },
 
    dispose : function() {
    
        if(this._timer) {
            this._timer.dispose();
            this._timer = null;
        }
        this._tickHandler = null;
    
        // TODO: add your cleanup code here
        // Detach event handlers
        if (this._keyupHandler) {
            $removeHandler(this.get_element(), "keyup", this._keyupHandler);
            this._keyupHandler = null;
        }
        if (this._keydownHandler) {
            $removeHandler(this.get_element(), "keydown", this._keydownHandler);
            this._keydownHandler = null;
        }
 
        DelayedSubmit.DelayedSubmitBehavior.callBaseMethod(this, 'dispose');
    },
 

    _onkeyup : function(ev) {
        var k = ev.keyCode ? ev.keyCode : ev.rawEvent.keyCode;        
        if (k != Sys.UI.Key.Tab) {
            this._timer.set_enabled(true);
        }        
    },
    
    
    _onkeydown : function(ev) {
        this._timer.set_enabled(false);
    },
 

    _onTimerTick : function(sender, eventArgs) {
        this._timer.set_enabled(false);
        
        if(this._text != this.get_element().value) {
            this._text = this.get_element().value;
            
            //alert('fire');
            this._changeHandler(); //this.get_element().onchange(); //compare to this.changed.invoke(this, Sys.EventArgs.Empty);
        }
    },
 

    // TODO: (Step 2) Add your property accessors here
    //
    get_Timeout : function() {
        return this._TimeoutValue;
    },
 
    set_Timeout : function(value) {
        this._TimeoutValue = value;
    }
}
 
DelayedSubmit.DelayedSubmitBehavior.registerClass('DelayedSubmit.DelayedSubmitBehavior', Sys.UI.Behavior);
Remy Blaettler
Chief of the System
Supertext AG

GeneralRe: Good article... Pin
Midhunlal G27-Jun-12 4:56
memberMidhunlal G27-Jun-12 4:56 
GeneralRe: Good article... Pin
Midhunlal G28-Jun-12 2:00
memberMidhunlal G28-Jun-12 2:00 
GeneralRe: Good article... Pin
Member 958190931-Jan-13 18:14
memberMember 958190931-Jan-13 18:14 
QuestionGood stuff! :) Pin
palpacino10-Jan-12 15:02
memberpalpacino10-Jan-12 15:02 
AnswerRe: Good stuff! :) Pin
Remy Blaettler10-Jan-12 22:23
memberRemy Blaettler10-Jan-12 22:23 
GeneralMy vote of 1 Pin
bolikej2-Jan-11 14:36
memberbolikej2-Jan-11 14:36 
GeneralDoes not work with RequiredFieldValidator Pin
fronjm054-Mar-10 10:02
memberfronjm054-Mar-10 10:02 
QuestionHow can I achieve this in .net2.0? Pin
Mohammmed Farooq27-Jul-09 1:45
memberMohammmed Farooq27-Jul-09 1:45 
QuestionHow can i use your solution with DynamicPopulate Pin
Member 462413621-Jul-09 20:35
memberMember 462413621-Jul-09 20:35 
AnswerRe: How can i use your solution with DynamicPopulate Pin
Remy Blaettler21-Jul-09 22:27
memberRemy Blaettler21-Jul-09 22:27 
GeneralGreat job! Pin
xrobx2-Jun-08 23:01
memberxrobx2-Jun-08 23:01 
GeneralRe: Great job! Pin
Remy Blaettler26-Jul-08 3:53
memberRemy Blaettler26-Jul-08 3:53 
Answer"DefaultButton" property is not working [modified] Pin
Member 382740230-Apr-08 4:43
memberMember 382740230-Apr-08 4:43 
QuestionAutocompleteExtender Pin
Andrei Rinea18-Apr-08 23:33
memberAndrei Rinea18-Apr-08 23:33 
GeneralRe: AutocompleteExtender Pin
Remy Blaettler21-Apr-08 7:37
memberRemy Blaettler21-Apr-08 7:37 
AnswerRe: AutocompleteExtender Pin
Andrei Rinea21-Apr-08 8:40
memberAndrei Rinea21-Apr-08 8:40 
GeneralRe: AutocompleteExtender Pin
Remy Blaettler24-Apr-08 16:49
memberRemy Blaettler24-Apr-08 16:49 
GeneralI think there is a mistake. Pin
Matrix15-Apr-08 6:29
memberMatrix15-Apr-08 6:29 
GeneralRe: I think there is a mistake. Pin
Remy Blaettler17-Apr-08 2:40
memberRemy Blaettler17-Apr-08 2:40 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web03 | 2.8.150603.1 | Last Updated 11 Apr 2008
Article Copyright 2008 by Remy Blaettler
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid