Friday, October 12, 2012

Asp.Net Online Test with Timer

We got a requirement that, we need to implement logic for a timer which continues to run between page post backs. For each question the page sends a postback request to the server.

So to implement this logic, I used java script Timer with some custom functionality to maintain the clock time between the server round trips. Below is the code.

<div id="timer" style="height:30px; float:right; padding:3px" >
Time:<asp:Label ID="lblTimer" runat="server" ></asp:Label>
<asp:TextBox style="display:none" ID="tbTimer" runat="server"></asp:TextBox>
<asp:Button ID="hdnBtnTimeOut" OnClick="ExamTimeOut" runat="server" style="display:none" />
</div>

<script type="text/javascript" language="javascript">
var Timer;
var TotalSeconds;


function CreateTimer(TimerID, Time) {
        Timer = document.getElementById(TimerID);
        TotalSeconds = Time;
       
        UpdateTimer()
        window.setTimeout("Tick()", 1000);
}


function Tick() {
        if (TotalSeconds <= 0) {
            alert("Time's up!")
            document.getElementById('<%=hdnBtnTimeOut.ClientID %>').click();
                return;
        }

        TotalSeconds -= 1;
        UpdateTimer();
        window.setTimeout("Tick()", 1000);
}

function UpdateTimer() {
        var Seconds = TotalSeconds;
       
        var Days = Math.floor(Seconds / 86400);
        Seconds -= Days * 86400;

        var Hours = Math.floor(Seconds / 3600);
        Seconds -= Hours * (3600);

        var Minutes = Math.floor(Seconds / 60);
        Seconds -= Minutes * (60);


        var TimeStr = ((Days > 0) ? Days + " days " : "") + LeadingZero(Hours) + ":" + LeadingZero(Minutes) + ":" + LeadingZero(Seconds)


        Timer.innerHTML = TimeStr;
        document.getElementById('<%=tbTimer.ClientID %>').value = TimeStr;
}


function LeadingZero(Time) {

        return (Time < 10) ? "0" + Time : + Time;

}

</script>

C#
        private void SetTimer()
        {
            string time = tbTimer.Text;
            int totalSeconds = 0;
            if (!string.IsNullOrEmpty(time))
            {
                string[] timeParts = time.Split(':');
                string hours = timeParts[0];
                string minutes = timeParts[1];
                string secons = timeParts[2];

                int hoursCnt, minutesCnt, seconsCnt;

                Int32.TryParse(hours, out hoursCnt);
                Int32.TryParse(minutes, out minutesCnt);
                Int32.TryParse(secons, out seconsCnt);

                totalSeconds = hoursCnt * 60 * 60 + minutesCnt * 60 + seconsCnt;

                if (totalSeconds == 0)
                {
                    //Time up, Write you logic here,like exam report.
                    return;
                }
            }
            ScriptManager.RegisterStartupScript(this, this.GetType(), "startTimer", "CreateTimer('" + lblTimer.ClientID + "'," + totalSeconds + ");", true);
        }

//User clicks on this button ,to start the test.
protected void btnproceed_Click(object sender, EventArgs e)
        {
//Write ur logic , below EXAM_TIME is a constant variable.
            ScriptManager.RegisterStartupScript(this, this.GetType(), "startTimer", "CreateTimer('" + lblTimer.ClientID + "'," + EXAM_TIME + ");", true);
}

//User clicks on the “Next” button.

protected void btnnext_Click(object sender, EventArgs e)
        {
SetTimer();
}



protected void ExamTimeOut(object sender, EventArgs e)
        {
            SetTimer();
        }