ASP.Net AJAX Controls - Text Box Extender

3/4/2008

One of the things that I noticed was missing from the ASP.Net AJAX Control Toolkit was the ability to update a div or really anything from a text box. What I needed was a popup to show up with options depending on what was typed into the text box that the user could click on and take them directly to the suggested location. So I created a basic AJAX control to do just that:

KeyUpTextBoxExtender.cs

   1: using System.ComponentModel;
   2: using System.Web.UI;
   3: using System.Web.UI.WebControls;
   4: using AjaxControlToolkit;
   5:  
   6: [assembly: System.Web.UI.WebResource("AJAXControls.KeyUpTextBox.KeyUpTextBoxBehavior.js", "text/javascript")]
   7:  
   8: namespace AJAXControls.KeyUpTextBox
   9: {
  10:     /// <summary>
  11:     /// Class for adding the ability to call a function after a key up event in a text box
  12:     /// </summary>
  13:     [Designer(typeof(KeyUpTextBoxDesigner))]
  14:     [ClientScriptResource("AJAXControls.KeyUpTextBox.KeyUpTextBoxBehavior", "AJAXControls.KeyUpTextBox.KeyUpTextBoxBehavior.js")]
  15:     [TargetControlType(typeof(TextBox))]
  16:     public class KeyUpTextBoxExtender : ExtenderControlBase
  17:     {
  18:  
  19:         /// <summary>
  20:         /// The minimum length needed to start calling the function
  21:         /// </summary>
  22:         [ExtenderControlProperty()]
  23:         [DefaultValue(3)]
  24:         public int MinLength
  25:         {
  26:             get
  27:             {
  28:                 return GetPropertyValue("MinLength", 3);
  29:             }
  30:             set
  31:             {
  32:                 SetPropertyValue("MinLength", value);
  33:             }
  34:         }
  35:  
  36:         /// <summary>
  37:         /// The amount of time it waits for a response
  38:         /// </summary>
  39:         [ExtenderControlProperty()]
  40:         [DefaultValue(1000)]
  41:         public int TimeOut
  42:         {
  43:             get
  44:             {
  45:                 return GetPropertyValue("TimeOut", 1000);
  46:             }
  47:             set
  48:             {
  49:                 SetPropertyValue("TimeOut", value);
  50:             }
  51:         }
  52:  
  53:         /// <summary>
  54:         /// The id of the control to update
  55:         /// </summary>
  56:         [ExtenderControlProperty()]
  57:         [RequiredProperty()]
  58:         [IDReferenceProperty(typeof(WebControl))]
  59:         public string UpdateControlID
  60:         {
  61:             get
  62:             {
  63:                 return GetPropertyValue("UpdateControlID", "");
  64:             }
  65:             set
  66:             {
  67:                 SetPropertyValue("UpdateControlID", value);
  68:             }
  69:         }
  70:  
  71:         /// <summary>
  72:         /// The container control id
  73:         /// </summary>
  74:         [ExtenderControlProperty()]
  75:         [IDReferenceProperty(typeof(WebControl))]
  76:         public string ContainerControlID
  77:         {
  78:             get
  79:             {
  80:                 return GetPropertyValue("ContainerControlID", "");
  81:             }
  82:             set
  83:             {
  84:                 SetPropertyValue("ContainerControlID", value);
  85:             }
  86:         }
  87:  
  88:         /// <summary>
  89:         /// The name of the function to call
  90:         /// </summary>
  91:         [ExtenderControlProperty()]
  92:         [RequiredProperty()]
  93:         public string ScriptName
  94:         {
  95:             get
  96:             {
  97:                 return GetPropertyValue("ScriptName", "");
  98:             }
  99:             set
 100:             {
 101:                 SetPropertyValue("ScriptName", value);
 102:             }
 103:         }
 104:  
 105:         /// <summary>
 106:         /// The name of the page on which to call the function
 107:         /// </summary>
 108:         [ExtenderControlProperty()]
 109:         [RequiredProperty()]
 110:         public string ScriptLocation
 111:         {
 112:             get
 113:             {
 114:                 return GetPropertyValue("ScriptLocation", "");
 115:             }
 116:             set
 117:             {
 118:                 SetPropertyValue("ScriptLocation", value);
 119:             }
 120:         }
 121:     }
 122: }

KeyUpTextBoxBehavior.js

   1: /// <reference name="AjaxControlToolkit.ExtenderBase.BaseScripts.js" assembly="AjaxControlToolkit" />
   2:  
   3: Type.registerNamespace('AJAXControls.KeyUpTextBox');
   4:  
   5: AJAXControls.KeyUpTextBox.KeyUpTextBoxBehavior = function(element) {
   6:  
   7:     AJAXControls.KeyUpTextBox.KeyUpTextBoxBehavior.initializeBase(this, [element]);
   8:     this._UpdateControlIDValue = null;
   9:     this._ContainerControlIDValue = null;
  10:     this._Counter = 0;
  11:     this._MinLengthValue = 3;
  12:     this._ScriptLocationValue = null;
  13:     this._ScriptNameValue = null;
  14:     this._TimeOutValue = 1000;
  15: }
  16:  
  17: AJAXControls.KeyUpTextBox.KeyUpTextBoxBehavior.prototype = {
  18:  
  19:     initialize: function() {
  20:         AJAXControls.KeyUpTextBox.KeyUpTextBoxBehavior.callBaseMethod(this, 'initialize');
  21:         Sys.UI.DomEvent.addHandler(this.get_element(), 'keyup',
  22:         Function.createDelegate(this, this._onkeyup));
  23:         this._onkeyup();
  24:     },
  25:  
  26:     dispose: function() {
  27:         AJAXControls.KeyUpTextBox.KeyUpTextBoxBehavior.callBaseMethod(this, 'dispose');
  28:     },
  29:  
  30:     _onkeyup: function() {
  31:         var NumKeys = this.get_element().value.length;
  32:         if (NumKeys >= this._MinLengthValue) {
  33:             var e = this.get_element().value;
  34:             ++this._Counter;
  35:  
  36:             Sys.Net.WebServiceProxy.invoke(this._ScriptLocationValue, this._ScriptNameValue, false, { "contextKey": e }, Function.createDelegate(this, this._onMethodComplete), Function.createDelegate(this, this._onMethodError), this._Counter, this._TimeOutValue);
  37:         }
  38:         else {
  39:             if (this._ContainerControlIDValue != null) {
  40:                 $get(this._ContainerControlIDValue).style.display = "none";
  41:             }
  42:             else {
  43:                 $get(this._UpdateControlIDValue).style.display = "none";
  44:             }
  45:         }
  46:     },
  47:  
  48:     _onMethodComplete: function(result, userContext, methodName) {
  49:         if (this._Counter == userContext) {
  50:             if (this._ContainerControlIDValue != null) {
  51:                 $get(this._ContainerControlIDValue).style.display = "block";
  52:             }
  53:             else {
  54:                 $get(this._UpdateControlIDValue).style.display = "block";
  55:             }
  56:             $get(this._UpdateControlIDValue).innerHTML = result;
  57:         }
  58:     },
  59:  
  60:     _onMethodError: function(webServiceError, userContext, methodName) {
  61:         if (this._ContainerControlIDValue != null) {
  62:             $get(this._ContainerControlIDValue).style.display = "block";
  63:         }
  64:         else {
  65:             $get(this._UpdateControlIDValue).style.display = "block";
  66:         }
  67:         if (webServiceError.get_timedOut()) {
  68:             $get(this._UpdateControlIDValue).innerHTML = AjaxControlToolkit.Resources.DynamicPopulate_WebServiceTimeout;
  69:         } else {
  70:             $get(this._UpdateControlIDValue).innerHTML = String.format(AjaxControlToolkit.Resources.DynamicPopulate_WebServiceError, webServiceError.get_statusCode());
  71:             $get(this._UpdateControlIDValue).innerHTML += this._ScriptLocationValue;
  72:             $get(this._UpdateControlIDValue).innerHTML += this._ScriptNameValue;
  73:         }
  74:     },
  75:  
  76:     get_UpdateControlID: function() {
  77:         return this._UpdateControlIDValue;
  78:     },
  79:  
  80:     set_UpdateControlID: function(value) {
  81:         this._UpdateControlIDValue = value;
  82:     },
  83:  
  84:     get_TimeOut: function() {
  85:         return this._TimeOutValue;
  86:     },
  87:  
  88:     set_TimeOut: function(value) {
  89:         this._TimeOutValue = value;
  90:     },
  91:  
  92:     get_ContainerControlID: function() {
  93:         return this._ContainerControlIDValue;
  94:     },
  95:  
  96:     set_ContainerControlID: function(value) {
  97:         this._ContainerControlIDValue = value;
  98:     },
  99:  
 100:     get_MinLength: function() {
 101:         return this._MinLengthValue;
 102:     },
 103:  
 104:     set_MinLength: function(value) {
 105:         this._MinLengthValue = value;
 106:     },
 107:  
 108:     get_ScriptLocation: function() {
 109:         return this._ScriptLocationValue;
 110:     },
 111:  
 112:     set_ScriptLocation: function(value) {
 113:         this._ScriptLocationValue = value;
 114:     },
 115:  
 116:     get_ScriptName: function() {
 117:         return this._ScriptNameValue;
 118:     },
 119:  
 120:     set_ScriptName: function(value) {
 121:         this._ScriptNameValue = value;
 122:     }
 123: }
 124:  
 125: AJAXControls.KeyUpTextBox.KeyUpTextBoxBehavior.registerClass('AJAXControls.KeyUpTextBox.KeyUpTextBoxBehavior', AjaxControlToolkit.BehaviorBase);

The control allows you to specify a textbox, a div to fill in with the info it receives from the function call, as well as a container for that div. For instance, let's say you have a div that will have a close button, a header, and a footer, as well as an inner div where you want the information sent back by the function call. This allows you to do that, however the container is optional.

It also allows you to specify a function to call as well as the ability to specify which file that function is within. Just make sure to use the same sort of declarations you would if you were using the Control Toolkit:

   1: [System.Web.Services.WebMethod]
   2: [System.Web.Script.Services.ScriptMethod]
   3: public string GetNames(string contextKey) { ... } 

You also have the ability to specify the minimum length of the text in the text box prior to it firing off the function calls. The default being 3 in this case.

This is actually the first AJAX Control that I created for ASP.Net and I have to say that if you ever plan on making your own, look at the code within the Control Toolkit as it is a great learning source. Anyway, download the control and try it out. Everything should be commented to where you can use it. And as always, leave comments/suggestions for improvement.



Comments