Welcome to AspAdvice Sign in | Join | Help

Alessandro Gallo

.NET & Beyond
An Atlas behavior to handle text changes
A user on the ASP.NET Forums (dleffel, in this thread) has an interesting requirement. Basically, he wants a 'changed' event to be fired when the text in an input field changes, but only after the user has paused/stopped typing for a certain amount of time.

To accomplish this task, I've coded a simple behavior. You may want to check this post for some details on how to code an Atlas behavior. When attached to an input control like a textbox, this behavior waits for the specifed amount of time (the timeout property) after the used has paused/stopped typing, then if the text has changed it raises a changed event.

TextChangedBehavior.js

Type.registerNamespace('AtlasNotes.UI');

AtlasNotes.UI.TextChangedBehavior = function() {
    AtlasNotes.UI.TextChangedBehavior.initializeBase(this);
   
    // Private members.
    var _text;
    var _timeout = 500;
    var _timer;
    var _keydownHandler;
    var _keyupHandler;
    var _tickHandler;
   
    // Properties.
    this.get_timeout = function() {
        return _timeout;
    }
    this.set_timeout = function(value) {
        if(value != _timeout) {
            _timeout = value;
            if(_timer) {
                _timer.set_interval(_timeout);
            }
            this.raisePropertyChanged('timeout');
        }
    }
    // Events.
    this.changed = this.createEvent();
   
    // Initialize / Dispose.
    this.initialize = function() {
        AtlasNotes.UI.TextChangedBehavior.callBaseMethod(this, 'initialize');
        _text = this.control.element.value;
        _tickHandler = Function.createDelegate(this, this._onTimerTick);
       
        _timer = new Sys.Timer();
        _timer.set_interval(_timeout);
        _timer.tick.add(_tickHandler);
       
        _keydownHandler = Function.createDelegate(this, keydownHandler);
        this.control.element.attachEvent('onkeydown', _keydownHandler);
       
        _keyupHandler = Function.createDelegate(this, keyupHandler);
        this.control.element.attachEvent('onkeyup', _keyupHandler);
    }
    this.dispose = function() {
        if(_timer) {
            _timer.tick.remove(_tickHandler);
            _timer.dispose();
            _timer = null;
        }
        _tickHandler = null;
       
        this.control.element.detachEvent('onkeydown', _keydownHandler);
        _keydownHandler = null;
       
        this.control.element.detachEvent('onkeyup', _keyupHandler);
        _keyupHandler = null;
           
        AtlasNotes.UI.TextChangedBehavior.callBaseMethod(this, 'dispose');
    }
   
    // Descriptor.
    this.getDescriptor = function() {
        var td = AtlasNotes.UI.TextChangedBehavior.callBaseMethod(this, 'getDescriptor');
       
        td.addProperty('timeout', Number);
        td.addEvent('changed', true);
       
        return td;
    }
   
    // Event Handlers.
    function keydownHandler() {
        _timer.set_enabled(false);
    }
    function keyupHandler() {
        var e = window.event;
        if (e.keyCode != Sys.UI.Key.Tab) {
            _timer.set_enabled(true);
        }       
    }
    this._onTimerTick = function() {
        _timer.set_enabled(false);
       
        if(_text != this.control.element.value) {
            _text = this.control.element.value;
           
            this.changed.invoke(this, Sys.EventArgs.Empty);
        }
    }
}
AtlasNotes.UI.TextChangedBehavior.registerClass('AtlasNotes.UI.TextChangedBehavior', Sys.UI.Behavior);
Sys.TypeDescriptor.addType('script', 'textChangedBehavior', AtlasNotes.UI.TextChangedBehavior);

Finally, here's a basic example to test the behavior:

TextChangedBehavior.aspx

<%@ Page Language="C#" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title>TextChangedBehavior Example</title>
</head>
<body>
    <form id="form1" runat="server">
    <atlas:ScriptManager ID="sm" runat="server">
        <Scripts>
            <atlas:ScriptReference Path="ScriptLibrary/TextChangedBehavior.js" />
        </Scripts>
    </atlas:ScriptManager>
    <div>
        <asp:TextBox ID="myTextBox" runat="server"></asp:TextBox>
    </div>
    <script type="text/javascript">
        function onTextChange() {
            alert('text changed!');
        }
    </script>
    </form>
    <script type="text/xml-script">
        <page>
            <components>
                <textBox id="myTextBox">
                    <behaviors>
                        <textChangedBehavior timeout="2000"
                                             changed="onTextChange" />
                    </behaviors>
                </textBox>
            </components>
        </page>
    </script>
</body>
</html>

UPDATES:

  • 03/23/2006 - The code now runs in the March CTP.

 

Sponsor
Posted: Saturday, February 25, 2006 11:03 AM by Garbin

Comments

Peter Kellner said:

A wonderful example. Thank you.
# February 28, 2006 12:01 PM

Peter Kellner said:

For some reason, this exact code doesn't want to work in a master page with simply the contentholders added. I've posted my code on asp.net replying to your posting. It is at:

http://forums.asp.net/1212542/ShowPost.aspx#1212542

Thanks again.
# February 28, 2006 12:37 PM

Garbin said:

Peter,

there's a problem in the ID you gave to the Atlas TextBox. You can read my reply here:
http://forums.asp.net/1212949/ShowPost.aspx#1212949

Hope this helps.
# February 28, 2006 6:38 PM

Peter Kellner said:

It's me again! I want to update my demo app using the latest March Atlas Bits. MS seems to have changed how they access the script library. Do you have any notes on what is necessary to make the textbox stuff work in the new Atlas? Can you tell if MS natively supports textbox update now?

thanks
# March 20, 2006 2:38 PM

Garbin said:

Peter,

the code has been updated for the March CTP. I've tested the example on Firefox and it seems to work correctly. I haven't yet seen a similar functionality shipped with the Atlas framework.
# March 23, 2006 7:18 AM

Peter Kellner said:

Thanks, worked as advertised in firefox. Unfortunately, the other problem I run into with firefox is that I'm using master pages and apparently the control does not get named the same in FF as it does in IE. Garbin suggested I write a server control that inherits from TExtBox and implements IScriptControl. Hmm. Never done a server control and am a javascript neophyte.

Good job! -Peter
# March 23, 2006 4:02 PM

Peter Kellner said:

I just took a look at custom controls. May be pretty easy. I think I'll take a wack at. I maybe back with problems though.
# March 23, 2006 4:42 PM

defduane said:

How can this behavior be used to invoke an update of an atlas updatepanel? I can't get <atlas:ControlEventTrigger ControlID="myTextBox" EventName=?? /> to work no matter what the event is set to.

Without using any of this code, a controlvaluetrigger will work, the only problem is you must click off the textbox before the update fires.

Am i missing something?

thanks
# April 17, 2006 8:07 PM

Garbin said:

defduane,

a ControlEventTrigger must target a "server-side" event, i.e. an event raised by the server when a postback occurs. As you noticed, if the TextBox has the AutoPostBack property set to true, it will post back when the control looses focus and the text has changed, thus allowing to trigger the update.

So, with the code provided it's not possible to trigger an update from the TextChangedBehavior.
# April 19, 2006 6:27 PM

defduane said:

thanks Garbin,

I still am missing something...what is the point of atlas in this example? the functionality of this example could be done using javascript only, no?

If the function that this example executes is javascript, i.e. function onTextChange(), how can this be used to update a list in a gridview? I thought this was the intention of the original question.

thanks again.
# April 20, 2006 9:21 AM

Garbin said:

defduane,
I think that this example is interesting not only for the task that it performs, but also because shows an example of Atlas behavior, i.e. a little piece of client-side functionality that can be attached/removed to/from controls. Moreover, it can be used in declarative script, thus hiding the Javascript from the user. Finally, I think that it's not difficult to arrange the code and allow to invoke a partial postback, or maybe handling the textchanged event to do that.
# May 2, 2006 4:07 AM

Jessica said:


Garbin thanks, this example is very interesting!
But... I have a problem... Is possible call an event with only textchanged without need of the timeout? I would want to reproduce this example http://atlas.asp.net/docs/Walkthroughs/GetStarted/Declarative.aspx, but without clicking on button.
Thanks in advance and sorry for English!  Jessica
# May 2, 2006 5:28 AM

Garbin said:

Jessica,
thank you for the feedback, regarding the timeout you could try to set it to a reasonably low value, for example try timeout="10" or timeout="20". Since the value is expressed in milliseconds, it should give you the feel of a real-time update. Let me know if it works!
Garbin
# May 2, 2006 8:37 AM

Jessica said:

Thanks for the answer Garbin!!!
I would want to know if it is possible raise the textchanged event not with timeout but on onblur event... only when the textbox loses the focus. Is possible?
Thank you!
Jessica
# May 2, 2006 8:50 AM

Randy G. Braze said:

Garbin,

When I implement this script along with the Atlas Contol Toolkit Extender, the script generates an error.

The line causing the problem is:

Type.registerClass('AtlasExamples.WebUI.TextChangedBehavior', Web.UI.Behavior);

The error is: Microsoft JScript runtime error. ‘Web’ is undefined.

Do you have any clues what's causing this problem. When I remove the control toolkit stuff, it works just fine.

Randy
# May 2, 2006 12:23 PM

Garbin said:

Randy,
I'm pretty sure that you are using the code relative to the Feb CTP. Since the March CTP, the namespace Web has been renamed to Sys. You can copy the updated code from this blog post.
Garbin
# May 2, 2006 12:44 PM

Randy G. Braze said:

Very good! Thanks. I'm cuttin' and pastin' right now <G>.

Randy
# May 3, 2006 11:14 AM

jacec said:

Using this behavior js file and the following code, with the subsquent trigger, will cause an updatepanel update, without having to leave the text box:

<script type="text/javascript">
       
       function onTextChange() {
               
           var t = document.getElementById("myTextBox");            
               t.blur();
               t.focus();

       </script>
               <Triggers>
                   <atlas:ControlEventTrigger ControlID="myTextBox" EventName="TextChanged" />
               </Triggers>

And thank you Garbin for this great code.
# July 7, 2006 10:55 AM

Peter Kellner said:

Hi,
I'm having problems with the June CTP. (my code using the above textchanged script worked in March CTP).

Specifically, in the TextChangedBehavior.js file on line 96

"Web.TypeDescriptor.addType('script', 'textChangedBehavior', AtlasExamples.WebUI.TextChangedBehavior);
"

I'm getting the error:  "Unrecognized tag script:textChangedBehavior".

Any thoughts or examples of using the textchanged script with June CTP Atlas?

Thanks

-Peter Kellner
# July 14, 2006 2:16 PM

Peter Kellner said:

Hi,
I'm having problems with the June CTP. (my code using the above textchanged script worked in March CTP).

Specifically, in the TextChangedBehavior.js file on line 96

"Web.TypeDescriptor.addType('script', 'textChangedBehavior', AtlasExamples.WebUI.TextChangedBehavior);
"

I'm getting the error:  "Unrecognized tag script:textChangedBehavior".

Any thoughts or examples of using the textchanged script with June CTP Atlas?

Thanks

-Peter Kellner
# July 14, 2006 2:17 PM

Peter Kellner said:

Hi Garbin,

My article referring and using your textchanged stuff just got published on MSDN and I'm getting a bunch of questions on why it doesn't work with June CTP.  If you could take a look at the textchanged stuff with the June release, I'd be really really happy.

Thanks.

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnaspp/html/membershipeditoratlas.asp

PS:  the CAPCHA image is much better now.  Hope you're not getting spammed.
# July 17, 2006 8:48 PM

Garbin said:

Peter, I've tested the behavior on the June CTP, it works correctly for me. Also, in a comment above, you pasted a statement where there's a reference to Web.TypeDescriptor.addType, but the Web namespace has been renamed to Sys. Be sure to use the updated version of the script. Let me know if it didn't solve your problems (feel free to use the contact form if you want).
Garbin
# July 18, 2006 2:50 AM

Jesus De La Cruz said:

Hi, Garbin & Peter Kellner:

The problem Peter has is very easy to solve an has nothing to do with ATLAS.

I have exactly the same problem and  here is what you need to do to solve it:

Just check that the ScriptLibrary Directory(The one that have TextChangedBehavior.js) and the aspx page are in the SAME Directory.

It could be an "Admin" directory or the root directory of your Application.

Hope this helps.
# July 19, 2006 7:20 PM

Peter Kellner said:

Yes, Thanks Garbin.  I was using a previous version with the web namespace wrong.  I changed it as you suggest and it is working fine now.  I have the updated script on my site now at this URL in case anyone is trying to use it any having problems.

http://peterkellner.net/?p=39

Thanks for the help
# July 20, 2006 6:22 PM

Albert Pascual said:

How do you make a call to the server side function aspx.cs?
Cheers
Al
# July 22, 2006 4:16 PM

Garbin said:

Albert: in the changed event handler, you could invoke a Page method, or perform a postback using  a Sys.WebForms.PostBackAction instance. In this case, you'll obtain an asynchronous postback if the associated control is inside an UpdatePanel.
# July 29, 2006 4:43 AM

Jan said:

Hello,

if you use an AutoCompleteExtender for the same TextBox you will get an ecxeption from your Browser. Try it.

Here is the Code:

<asp:TextBox ID="TextBox1" runat="server" AutoPostBack="true"></asp:TextBox>
                   <atlas:AutoCompleteExtender ID="ac1" runat="server">
                       <atlas:AutoCompleteProperties Enabled="true" MinimumPrefixLength="1" ServicePath="Webservice.asmx"
                           TargetControlID="TextBox1" ServiceMethod="Schlagwörter" />
                   </atlas:AutoCompleteExtender>

has everyone an idea ?
Thanks
Jan
# August 3, 2006 12:57 PM

Garbin said:

Jan: the AutoCompleteBehavior has got its internal timer to fire the call to the web service, thus using the TextChangeBehavior is not  very useful in this case.
# August 3, 2006 6:47 PM

Jan said:

Garbin: yes, i need both, the AutoCompleteExtender to show suggests and the TextChangeBehavior to show search results live, like this http://livesearch.alltheweb.com/?ek=1
# August 4, 2006 1:51 AM

Garbin said:

Jan: I understand your point, did you check the example of auto completion provided in my GeotagIt mashup? It is the feed search dropdown list embedded in the mini RSS reader. Take a look at it because it implements a similar functionality and I believe you can add the TextChangeBehavior to the TextBox without problems.
Garbin
# August 4, 2006 5:50 AM

Chris said:

Hi Garbin and thanks for your code.

I'm using it to trigger a database search and display the results in a GridView (similar to what Peter Keller has done).  My problem is that the search is inconsistent ... if I type a few characters, the search starts and if I type another character or two before the search ends, they are ignored by the search and not used to filter the results returned.  Do you have any ideas for a solution for this issue?

Thanks!

adf471587879rzq
# August 9, 2006 3:06 PM

Jan said:

Hello Garbin, i get the error in this Line of the  
TextChangeBehavior.js
this.initialize = function() {

The errormessage is: "Duplicate use of id "TextBox1" for object of type "Sys.UI.TextBox".

Without the AutoCompleteExtender there is no error.
# August 9, 2006 7:20 PM

Garbin said:

Jan: it sounds like you are declaring two Atlas controls for the same TextBox. One is declared by  the AutoCompleteExender, maybe you are declaring the other in a xml-section? You should attach the behavior to the same TextBox control declared by the AutoCompleteExtender, though I think it will conflict with the TextChangeBehavior due to its implementation.
# August 12, 2006 2:23 PM

Sam said:

Hi Garbin, this code is awesome, but I'd like to be able to pass a string through to the onTextChange() function.

I tried setting changed="onTextChange('String') in the textChangedBehavior tag but this breaks the behaviour...no errors, it just doesn't work any more.  Is there a way to do this without breaking it?
# August 15, 2006 12:09 PM

Garbin said:

Sam: you are using the onTextChange() function as an event handler, thus it will be called with the  "sender" and EventArgs arguments. Consider adding a property to the behavior, that holds the string you want to access and then retrieve it in the event handler (the sender parameter contains a reference to the behavior itself).
# August 17, 2006 5:10 AM

Sam said:

Ah, I see...I think.  I'm a bit of a JS newbie, I never really went into event handling.  The string I wanted to pass the onTextChange function is actually just the ClientID of the textbox - is there an easier way to access this in onTextChange, using the sender parameter or something?  The reason for passing the ID is so that I can reuse my onTextChange function if there are multiple textboxes utilising this behaviour on the same page.
# August 17, 2006 2:18 PM

Garbin said:

Sam: sender.control.get_id() should give the clientID of the TextBox.
# August 18, 2006 3:27 PM

Sam said:

That worked like a dream; thanks a lot!

# August 23, 2006 8:01 AM

Malcolm said:

I'm have a problem when running your script.

I'm getting the error:  "Unrecognized tag script:textChangedBehavior".

I'm using your script with the June version of Atas

# October 1, 2006 11:00 PM

Malcolm said:

I'm have a problem when running your script.

I'm getting the error:  "Unrecognized tag script:textChangedBehavior".

I'm using your script with the June version of Atas

# October 1, 2006 11:04 PM

Malcolm said:

Thanks have fixed the problem issue with script path and folder name

# October 2, 2006 12:19 AM

mak said:

Hello!

I want ask about update panel again.

I have

<asp:TextBox ID="TextEdit" runat="server"  AutoPostBack="true" OnTextChanged="On_TextChanged"/>

and updatepanel with

<atlas:ControlValueTrigger ControlID="TextEdit" PropertyName="Text" />

I use this behaviour with next

function onTextChange() {

if ((key == Sys.UI.Key.Space) || (key == Sys.UI.Key.Return))                      __doPostBack('TextEdit', '');

}

It works fine at my computer, but not always at another (sometimes it works like original OnTextChanged - only when TextBox lost focus).

Is this code correct?

How I have to modify it to work always and anywhere?

thanks

# October 2, 2006 2:41 AM

Garbin said:

@mak: check one of my last posts:

http://aspadvice.com/blogs/garbin/archive/2006/10/04/SliderExtender_3A00_-using-the-Slider-as-a-Trigger-for-the-UpdatePanel.aspx

it shows some js code to programmatically fire the change event on a textbox. You could add this code to the onTextChange() function. At this point, setting AutoPostBack="true" on the textbox should do the trick.

# October 5, 2006 8:04 AM

Atlas notes said:

Do you remember the TextChangedBehavior ? It is a MS AJAX Behavior associated to a textbox, that allows

# October 28, 2006 7:30 PM

Alidad Modjtabai said:

maybe you can put sample on there so people see the idea. thanks.

Alidad

# October 29, 2006 10:24 AM

leon said:

Could anybody please post a simple example that can work with the TextChangedBehavior?

i have tried the example above of Garbin with the newest version of Atlas, but it doesnot work.

Really appreciate any helps.

Leon

# December 16, 2006 1:25 AM

ASP.NET AJAX Toolkit Forum Posts said:

When Atlas was first released I had need to react to the user as they typed in a text box and ran across

# January 23, 2007 7:21 PM

Remy Blaettler said:

I've implemented your approach as an ASP.NET Ajax Extender Control, it's a bit easier to use this way and it works with the current release of the Ajax Toolkit.

http://remy.supertext.ch/2007/06/see-search-results-as-you-type-an-aspnet-ajax-control/

There is a live demo and the source code in my post. Have fun!

# June 20, 2007 4:09 PM

truly the only program that do conceive everyone i_2 said:

CheapAir Jordan 1 (I), previously innovato CheapAir Jordan 1 (I) r struc Trx ture,Trx, boundary,Michael Kors Bags Outlet, as well as perhaps a malbox. can make you offer usually the TRX within you will get an and substantial combating doing e Michael

# April 30, 2014 4:21 PM
New Comments to this post are disabled