Handling KeyPress Events on a VWG Textbox using a Client-Side Timer
Categories: Texts, Custom Controls
|
Tags: Architects, Developers, Events, C#, 3. Advanced, Customization, v6.3
Revision:
2
Posted:
07/Jan/2009
Updated:
27/Oct/2010
Status:
Publish
Types: Code
|
Standard ajax involves a heavy use of client side timers. Visual Web Gui shields developers from alot of the messy details, but there are times when you have to get messy. I want to filter data based on the value in a textbox. However, I don't want to require a button click or enter press, and I don't want to handle all the keypress events on the server as postbacks. Take this for example:  All I did was type kite, and some search results were returned. To accomplish this in Visual Web Gui, we could handle each textchanged event on the server, but this requires a postback for every key press. Not a good solution for the web. The original idea was to create a client side timer that would be started when the text was changed. I collaborated with Ryan Hatch, who did all of the coding, to put this together - thanks, Ryan! Here is a live demonstration: Could not parse video source.
Please follow the next instructions to embed video fragments:
- you can directly use videos from:
www.youtube.com
video.google.com
www.vimeo.com
- you can directly reference video fragments of types: FLV, MOV, MP4 and F4V
- for SWF Camtasia flash files should be HTML/HTML file and additional
[videoname]_config.xml or ProductionInfo.xml file.
Check the video URL if you can't see the fragment.
As you can see, we've got 2 ways to fire the events: while typing is occurring, or after typing is completed. That behavior is set here:  How does this work? First, a quick look at the Visual Studio Solution:  Ryan took the TextBox.js and TextBox.xslt files from the VWG Sources folder, modified them, and created a class that inherits from the TextBox class:
public partial class TimedTextBox : TextBox
{
public TimedTextBox()
{
InitializeComponent();
}
/// <summary>
/// Number of milliseconds that the timer will run before KeyPress event is raised
/// </summary>
[Description("Number of milliseconds that the timer will run before KeyPress event is raised")]
public int TimerLength { get; set; }
/// <summary>
/// Sets whether or not a running client timer will be reset when a key is pressed on the client.
/// </summary>
[Description("Sets whether or not a running client timer will be reset when a key is pressed on the client.")]
public bool ResetClientTimerOnKeyPress { get; set; }
protected override void RenderAttributes(
Gizmox.WebGUI.Common.Interfaces.IContext objContext,
Gizmox.WebGUI.Common.Interfaces.IAttributeWriter objWriter)
{
objWriter.WriteAttributeString("TimerLength", TimerLength);
if (this.ResetClientTimerOnKeyPress == true)
objWriter.WriteAttributeString("ResetClientTimerOnKeyPress", 1);
else
objWriter.WriteAttributeString("ResetClientTimerOnKeyPress", 0);
base.RenderAttributes(objContext, objWriter);
}
}
We added 2 properties: * TimerLength: Number of milliseconds that the timer will run before code is executed * ResetClientTimerOnKeyPress: A boolean value that sets whether or not a running client timer will be reset when a key is pressed on the client. And we've overriden the RenderAttributes() method in the base class to include these properties as attributes in the html output. TimedTextBox.xslt: here we've added a an event handler to the html textbox, to call a javascript method:
<!--This is our hook into JavaScript, using OnKeyPress-->
<xsl:attribute name="onkeypress">
mobjApp.TimedTextBox_SetTimer('<xsl:value-of select="@Id"></xsl>',this,window);
mobjApp.TextBox_KeyPress('<xsl:value-of select="@Id"/>',
'<xsl:value-of select="@Attr.CharacterValidationMask"/>',
'<xsl:value-of select="@Attr.CharacterValidationExpression"/>',window,this,event);
</xsl:attribute>
and here are the javascript methods: TimedTextBox.js
// Called whenever the user changes text in textbox
function TimedTextBox_SetTimer(strGuid, objInput, objWindow) {
// Get Current TimerID
var myTimerID = Data_GetAttribute(strGuid, "TimerID");
// Get ResetTimerOnKeyPress Flag
var myResetTimerOnKeyPress = Data_GetAttribute(strGuid, "ResetClientTimerOnKeyPress");
// Is there a Timer already running?
var myHasTimerRunning = false;
if (myTimerID != null && myTimerID != 'null') { myHasTimerRunning = true; }
// Should we start a new Timer?
if (myResetTimerOnKeyPress == 1 || myHasTimerRunning == false) {
// Create TimerID
var myNewTimerID = TimedTextBox_CreateGuid();
// Set Current TimerID
Data_SetAttribute(strGuid, "TimerID", myNewTimerID);
// Create Callback
var myFunction = function() { TimedTextBox_TimerExpired(myNewTimerID, strGuid, objInput, objWindow); };
// Get Timer Length
var myTimerLength = Data_GetAttribute(strGuid, "TimerLength");
// Start Timer
var myTimeout = Web_SetTimeout(myFunction, myTimerLength);
}
The behavior of the textbox is determined by attributes that we set earlier. Line 44 invokes VWG code that starts a timer, and then executes code when the timer is complete. Here is the code when the timer is complete:
function TimedTextBox_TimerExpired(strTimerID, strGuid, objInput, objWindow)
{
// Get Current TimerID
var myTimerID = Data_GetAttribute(strGuid, "TimerID");
// Is our TimerID the latest TimerID?
// We need this because - If user keeps typing, multiple timers will be running at once.
// Especially with the ResetClientTimerOnKeyPress flag
if (strTimerID == myTimerID) {
// Clear Timer - VWG Bug - setting null actually sets it to string 'null'!
Data_SetAttribute(strGuid, "TimerID", null);
// Raise Event (Fake the EnterKey to get TextChanged to Fire)
TextBox_Change(strGuid, objInput.value, objWindow, true);
}
By checking the TimerId value in line 56, we allow for the behavior to only send a call to the server if the id given for the timer matches what is currently stored in the textbox as an attribute. In line 62, we raise the Textbox_Change event. By the way, don't forget to declare the control in web.config:
<Controls>
<Control Type="MyControls.TimedTextBox.TimedTextBox, MyControls" ></Control>
</Controls>
Caveat: Does not yet work on multiline textboxes. This is a working concept that we hope can be integrated into the standard VWG textbox. Note: Codes are submitted as a .zip file to shorten your download time. After downloading it, you will need a program like Winzip to decompress it.
About the author
Related Articles
|
Texts
|
|
|
Tags:
Developers, Data Binding, Navigation, 1. Beginner, 2. Intermediate, Data Binding, Navigation, ASP.NET, Pre v6.3, v6.3, v6.4 and Later, 3. Advanced
|
|
|
This video demonstrates how to create and use a FCK Editor.
Tags:
Architects, Developers, Wrapper, 1. Beginner, 2. Intermediate, Pre v6.3, v6.3, v6.4 and Later, 3. Advanced
|
|
|
Tags:
Developers, 1. Beginner, 2. Intermediate, Customization, Pre v6.3, v6.3, v6.4 and Later, 3. Advanced
|
|
|
This is a code example to how to use the TextBox Validation class.
Tags:
Developers, 1. Beginner, 2. Intermediate, Customization, Pre v6.3, v6.3, v6.4 and Later, 3. Advanced
|
|
|
This application demonstrates how to use the Timer to update a TextBox and a ProgressBar control.
Tags:
Developers, Events, 1. Beginner, Pre v6.3, v6.3, v6.4 and Later, 2. Intermediate, 3. Advanced
|
|
|
Tags:
Architects, Developers, Wrapper, 1. Beginner, 2. Intermediate, 3. Advanced, Pre v6.3, v6.3, v6.4 and Later
|
|
|
|