Character Counting Extension

9/3/2008

I'm pretty sure that most of us have run into a situation where we've had to limit the size of a text box on a form. For instance, you may allow users to create a profile on your site with a description field and you only want it to be 1000 characters long. Limiting the size of the textbox is fairly simple (just set the MaxLength value). However setting that alone really doesn't help the user. Since the average person never really reads anything, he may skip the portion about the limited size, hit the max length, and then have no idea what is going on.

The easiest way to help a user know that an area has a character limit is to add a counter on the page.  Well I guess you could have the page yell at them the current values, but that might not go over so well... Plus you'd still have to give text clues to meet the whole 508/WAI accessibility standards... Anyway, since I don't like to rewrite code, nor having to write javascript code all the time, I wrote my own extender to take care of this for me:

CharacterCounterExtender.cs

   1: using System;
   2: using System.Web.UI.WebControls;
   3: using System.Web.UI;
   4: using System.ComponentModel;
   5: using System.ComponentModel.Design;
   6: using AjaxControlToolkit;
   7:  
   8: [assembly: System.Web.UI.WebResource("AJAXControls.CharacterCounter.CharacterCounterBehavior.js", "text/javascript")]
   9:  
  10: namespace AJAXControls.CharacterCounter
  11: {
  12:     [Designer(typeof(CharacterCounterDesigner))]
  13:     [ClientScriptResource("AJAXControls.CharacterCounter.CharacterCounterBehavior", "AJAXControls.CharacterCounter.CharacterCounterBehavior.js")]
  14:     [TargetControlType(typeof(Control))]
  15:     public class CharacterCounterExtender : ExtenderControlBase
  16:     {
  17:         // TODO: Add your property accessors here.
  18:         //
  19:         [ExtenderControlProperty()]
  20:         [RequiredProperty()]
  21:         [IDReferenceProperty(typeof(WebControl))]
  22:         public string UpdateControlID
  23:         {
  24:             get
  25:             {
  26:                 return GetPropertyValue("UpdateControlID", "");
  27:             }
  28:             set
  29:             {
  30:                 SetPropertyValue("UpdateControlID", value);
  31:             }
  32:         }
  33:  
  34:         [ExtenderControlProperty()]
  35:         [DefaultValue(0)]
  36:         public int MaxCharacters
  37:         {
  38:             get
  39:             {
  40:                 return GetPropertyValue("MaxCharacters", 0);
  41:             }
  42:             set
  43:             {
  44:                 SetPropertyValue("MaxCharacters", value);
  45:             }
  46:         }
  47:     }
  48: }

CharacterCounterBehavior.js

   1: // README
   2: //
   3: // There are two steps to adding a property:
   4: //
   5: // 1. Create a member variable to store your property
   6: // 2. Add the get_ and set_ accessors for your property
   7: //
   8: // Remember that both are case sensitive!
   9:  
  10:  
  11: /// <reference name="MicrosoftAjaxTimer.debug.js" />
  12: /// <reference name="MicrosoftAjaxWebForms.debug.js" />
  13: /// <reference name="AjaxControlToolkit.ExtenderBase.BaseScripts.js" assembly="AjaxControlToolkit" />
  14:  
  15:  
  16: Type.registerNamespace('AJAXControls.CharacterCounter');
  17:  
  18: AJAXControls.CharacterCounter.CharacterCounterBehavior = function(element) {
  19:     AJAXControls.CharacterCounter.CharacterCounterBehavior.initializeBase(this, [element]);
  20:  
  21:     // TODO : (Step 1) Add your property variables here
  22:     this._UpdateControlIDValue = null;
  23:     this._MaxCharactersValue = 0;
  24: }
  25: AJAXControls.CharacterCounter.CharacterCounterBehavior.prototype = {
  26:     initialize: function() {
  27:         AJAXControls.CharacterCounter.CharacterCounterBehavior.callBaseMethod(this, 'initialize');
  28:  
  29:         // TODO: Add your initalization code here
  30:         Sys.UI.DomEvent.addHandler(this.get_element(), 'keyup',
  31:             Function.createDelegate(this, this._onkeyup));
  32:         if (this._MaxCharactersValue != 0) {
  33:             $get(this._UpdateControlIDValue).innerHTML = this._MaxCharactersValue;
  34:         }
  35:         else {
  36:             $get(this._UpdateControlIDValue).innerHTML = this.get_element().value.length;
  37:         }
  38:     },
  39:  
  40:     _onkeyup: function() {
  41:         if (this._MaxCharactersValue != 0) {
  42:             $get(this._UpdateControlIDValue).innerHTML = this._MaxCharactersValue - this.get_element().value.length;
  43:         }
  44:         else {
  45:             $get(this._UpdateControlIDValue).innerHTML = this.get_element().value.length;
  46:         }
  47:     },
  48:  
  49:     dispose: function() {
  50:         // TODO: Add your cleanup code here
  51:  
  52:         AJAXControls.CharacterCounter.CharacterCounterBehavior.callBaseMethod(this, 'dispose');
  53:     },
  54:  
  55:     // TODO: (Step 2) Add your property accessors here
  56:     get_UpdateControlID: function() {
  57:         return this._UpdateControlIDValue;
  58:     },
  59:  
  60:     set_UpdateControlID: function(value) {
  61:         this._UpdateControlIDValue = value;
  62:     },
  63:     get_MaxCharacters: function() {
  64:         return this._MaxCharactersValue;
  65:     },
  66:  
  67:     set_MaxCharacters: function(value) {
  68:         this._MaxCharactersValue = value;
  69:     }
  70: }
  71: AJAXControls.CharacterCounter.CharacterCounterBehavior.registerClass('AJAXControls.CharacterCounter.CharacterCounterBehavior', AjaxControlToolkit.BehaviorBase);

This one is rather simple. The TargetControlID is the text box, UpdateControlID is the label/span/div/etc. that you want to show the number of characters, and there is an optional value that you can set (MaxCharacters). If MaxCharacters is set to anything other than 0, the counter shows the number of characters left and if it is set to 0 (or not set), then the counter simply counts the number of characters within the box. That's all there is to this one.



Comments