Click here to Skip to main content
Click here to Skip to main content

DHTML timer control

, 13 Oct 2005
Rate this:
Please Sign up or sign in to vote.
How to implement a reusable DHTML timer.

Sample Image - cronometro.png

Introduction

Since Microsoft released the .NET Framework, a lot of component vendors have surfaced and some of them provide amazing controls at a very cheap price. However sometimes a customer asks you for something too specific that you can't buy anywhere so you have to do it yourself.

This is the case for this article. A customer wanted to offer the possibility to do online tests on his portal. However he wanted to be able to know the remaining time exactly while doing the tests as well as be able to change the appearance without recompiling. Of course when the time expires he wanted the test to finish immediately. So it was time to make a custom control with DHTML support...

Background

In order to fully understand the code, you should be familiar with the design time framework, OO JavaScript and DHTML.

As I don't have time to change the source code you will see that it's in Spanish. I'm sorry if you don't understand it. It's a nice and very used language so you should start learning it Wink | ;-)

Using the code

Using the timer in your code is very easy:

  • Add the Cronometro control to the toolbox.
  • Add a Cronometro control to a WebForm.
  • Set the control's properties (in order to work properly you should set the script and the images folder using ScriptPath and ImagesPath properties).
  • Add the following HTTP handler to your web.config if you want the control to show the images in design time:
    <add verb="GET,POST" path="cronometro/*.ashx" 
      type="Flanders.Componentes.DesignTimeImageHandler, Cronometro" />
  • If you want to do something when the timer expires, handle the TimeOut event.

Here is a list of the properties of the control and what they do:

  • Duracion: TimeSpan when the timer expires.
  • ScriptPath: path to the folder containing crono.js (JavaScript logic).
  • ImagesPath: path to the folder with the images for the styles.
  • Estilo: style to use. There are 16 predefined styles. You can use your own style if you add your custom images to the ImagesPath folder.
  • CausaPostBack: if it's true, the control will cause postback when the timer expires generating the TimeOut event.
  • Ascendente: if it's true, the timer will count from 0 to the specified TimeSpan, otherwise from the specified TimeSpan to 0.
  • Mensaje: message to show when the timer expires.
  • MsgCssClass: CSS class to use for the message.
  • InitialTime: when exactly the timer starts (if it's not set, it will set the first time in the prerender stage).

For example, the demo project source code is:

// timer1: downwards, 1:00, causes postback
Cronometro1.Duracion = new TimeSpan(0, 1, 0);
Cronometro1.Ascendente = false;
this.Cronometro1.TimeOut += 
     new System.EventHandler(this.Cronometro1_TimeOut);
            
// timer2: downwards, 1:10
Cronometro2.Duracion = new TimeSpan(0, 1, 10);
Cronometro2.Ascendente = false;
Cronometro2.CausaPostBack = false;

// timer3: downwards, 1:20
Cronometro3.Duracion = new TimeSpan(0, 1, 20);
Cronometro3.Ascendente = false;
Cronometro3.CausaPostBack = false;

// timer4: upwards, 1:30, causes postback
Cronometro4.Duracion = new TimeSpan(0, 1, 30);
Cronometro4.Ascendente = true;
this.Cronometro4.TimeOut += 
     new System.EventHandler(this.Cronometro4_TimeOut);

The control uses a JavaScript file and has some predefined styles included so be sure to include them too in your deployments.

There's no limit to the number of timers you can use in a page. The control has been tested in IE 6.0, FireFox 1.0 and Opera 8.0.

Points of Interest

When you have to make a custom control that has logic on the server and the client side, it's important to think about how to pass values from the server side to the client side and vice versa.

In the server side I have all the properties but I needed to make them available to the client side because the timer is updated on the client side and the expiration check is also done there. IMHO the best way for doing this is to create a JavaScript class with the necessary fields and methods to have the job done. The control registers crono.js (where all the JavaScript code is) using RegisterClientScriptBlock in the prerender stage. Also, for each timer it creates an object with the following fields:

  • id: control's ClientID.
  • style: style to use.
  • expired: true if this timer has expired.
  • upwards: if true, the timer goes upwards, otherwise it goes downwards.
  • causePostBack: if it's true, the control will cause postback when the timer expires, generating the TimeOut event.
  • imgPath: path to the folder with the images for the styles.
  • timeSpan: instant of time when the timer expires.
  • serverInitTime: when exactly the timer starts (if it's not set, it will be set the first time in the prerender stage).
  • clientInitTime: client browser's time when the object is created.
  • serverInitLoadTime: instant of time when the page is in prerender stage for this roundtrip.

Instead of passing the InitialTime property directly I stored it in a hidden input field to allow to use the control to post a form's data to another page and be able to get the initial server time.

The client side methods are:

  • Tick: called every second to update the timer.
  • ShowRow: method to show/hide the row that shows a message when the timer expires.
  • DisplayTime: called from Tick to update the timer's digits.
  • GetInitialServerTime: helper method to get when exactly the timer starts (in server time).
  • GetTimeSpan: helper method to convert a string holding a TimeSpan value to a Date in JavaScript.

Only the Tick() method is a bit complex because it has the main timer logic.

The client side doesn't need to pass any value to the server side, as the server can find out if the timer has expired. However, the client side has to generate a server side event if the CausaPostBack property is set to true. In order to accomplish that, the control registers a function that will be called from Tick() when the timer expires, that uses Page.GetPostBackEventReference() to generate a postback.

The custom control has six images as children (one for each digit to show the timer in the format hh:mm:ss), that are created and added in CreateChildControls. The control implements INamingContainer to give unique names to its child controls as well as IPostBackEventHandler in order to be able to generate server side events.

The control has custom rendering to draw a table with two rows. On the first row it shows the digits, and the second row is used to display a message when the timer expires.

The control has a custom UITypeEditor to select the style as you can see in the picture at the top of this article.

To improve design time experience, I wanted the control to display images reflecting the selected style, but using ASP.NET 1.1 forces you to implement a custom handler to obtain the images from the assembly (in ASP.NET 2.0, this is improved, thanks to the WebResourceAttribute). The custom handler is implemented in the class DesignTimeImageHandler. The form used to select the control's style has some PictureBox controls and the framework automatically stores the associated bitmap as an image resource. Instead of adding the images as different embedded resources, I reused the images from the UITypeEditor.

The JavaScript needed by the control should be copied to a folder and the path should be set using the ImagesPath property. You can use a custom handler as done with the images in design time to obtain the JavaScript without having to set the path but I preferred this option because you can change the code easily without needing to recompile.

History

  • 2005/10/13 - Initial version.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

Share

About the Author

Manuel Abadia
Web Developer
Spain Spain
Manuel Abadia had his MS Degree in Computer Science (Univ. Murcia, Spain)
 
He is a Freelance Software Architect/Engineer and Trainer.
 
He sells his own components in his webpage (http://www.manuelabadia.com).
 
He was the Software Architect for the MoviTAP project that won the first prize in the Microsoft and Vodafone mobile web Services contest.
 
He has done some external work in companies like Namco America Inc. and Gaelco SA.
 
He has contributed to the MAME project (http://www.mamedev.com) for some years (and continues to do so eventually).

Comments and Discussions

 
QuestionHow to add pause functionality? PinmemberSatish Vellanki15-Mar-07 11:47 

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
Web01 | 2.8.141220.1 | Last Updated 13 Oct 2005
Article Copyright 2005 by Manuel Abadia
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid