Introduction
Most of us have come across Examination / Quiz projects. The important aspects of those projects is to have a timer that runs through the entire duration of the exam, having the timer running without reset by postbacks is the main concern of this article.
Background
The idea is to keep the value of the timer in view state and to supply the same on postback so that the timer will keep running from its previous value.
Using the Script
Understanding the script used here is not a big deal I guess, and am leaving it with a little explanation, go through the attachment for better understanding,
Timer is initiated in the page PreRender event, supplying the StartValue, Timerinterval and the clientId of the output element.
When the timer is started for the first timer, it is supplied with the duration of the examination say it is 30 min, and assume that the candidate spent 2 mins on a question and the postback occurs on 28 min, this value is kept in the view state and the same is used to start the timer again on the page PreRender event:
function myTimer(startVal,interval,outputId, dataField)
{
this.value = startVal;
this.OutputCntrl = document.getElementById(outputId);
this.currentTimeOut = null;
this.interval = interval;
myTimer.prototype.Seconds = function(value){
var hoursMillSecs = (this.Hours(value)*3600000)
var minutesMillSecs = (this.Minutes(value)*60000)
var total = (hoursMillSecs + minutesMillSecs)
var ans = Math.floor(((this.value - total)%60000)/1000);
this.OutputCntrl.innerHTML = this.Hours(current) + ':' + this.Minutes(current)
+ ':' + this.Seconds(current);
}
Keeping the Value in ViewState
You have to register the scrip with RegisterStartupScript in the codebehind file that supplies the view state value to the script and keeps the timer running.
Timer is initiated in PreRender event and the start value of the timer is requested from the view state and supplied to the timer, and this value changes on each postback as the exam is on progress.
void Page_PreRender(object sender, EventArgs e)
{
StringBuilder bldr = new StringBuilder();
bldr.AppendFormat("var Timer = new myTimer({0},{1},'{2}','timerData');",
this.timerStartValue, this.TimerInterval, this.lblTimerCount.ClientID);
bldr.Append("Timer.go()");
ClientScript.RegisterStartupScript(this.GetType(), "TimerScript",
bldr.ToString(), true);
ClientScript.RegisterHiddenField("timerData", timerStartValue.ToString());
}
private Int32 TimerInterval
{
get
{
object o = ViewState["timerInterval"];
if (o != null) { return Int32.Parse(o.ToString()); }
return 50;
}
set
{
ViewState["timerInterval"] = value;
}
}
Hope this will be a help to start your project. The attachment is prepared as a template that you can use for your project and can extend to meet your requirements.
History
- 13th September, 2010: Initial post