在本章中,我们将对“在线小测试”程序作两处修改。一是允许用户首先选择回答完问题所需要的时间,二是允许用户选择要回答多少个问题。
要把“在线小测试”程序转换为一个基于计时器的程序,只需修改两个页面,即quizpage.htm页面和globalfunctions.htm页面。
首先,需要修改的是quizpage.htm页面中小测试程序的开始表单,在新的程序中,将允许用户选择要回答多少个问题以及答题的时间限制。接下来,还要修改cmdstartquiz_onclick()函数,使得当在cmdstartquiz_onclick()函数中调用resetquiz()函数时,能够传入两个参数,一个参数表示答题的时间限制,另一个参数表示用户选择回答问题的数量。其中,resetquiz()函数是定义在globalfunctions.htm页面中的。
现在,我们讨论一下globalfunctions.htm页面本身,在globalfunctions.htm页面中,需要修改resetquiz()函数,以便根据用户选择的时间限制启动一个计时器。另外,还需要创建两个新的函数,以便对计时进行显示和处理:一个函数将在浏览器窗口的状态栏中显示剩余的时间以便提示用户,另一个函数将处理当计时器到点时的情况。
首先,我们来修改quizpage.htm页面,将quizpage.htm页面在文本编辑器中打开。
在quizpage.htm页面中,frmquiz表单目前仅包含一个按钮,将该表单修改为如下所示的代码:
<form name="frmquiz">
<p>
number of questions <br>
<select name="cbonoquestions" size="1">
<option value="3">3
<option value="5">5
</select>
</p>
<p>
time limit <br>
<select name="cbotimelimit" size="1">
<option value="-1">no time limit
<option value="60">1 minute
<option value="180">3 minutes
<option value="300">5 minutes
</select>
</p>
<input name=cmdstartquiz type=button value="start quiz"
onclick="return cmdstartquiz_onclick()">
</form>
在该表单中,添加了两个新的<select>标记,以创建两个下拉列表框。第一个下拉列表框允许用户选择愿意回答多少个问题,第二个下拉列表框则允许用户设置回答问题的时限。
接下来,修改页面顶部的cmdstartquiz_onclick()函数。
<script language=javascript>
function cmdstartquiz_onclick()
{
var cbonoquestions = document.frmquiz.cbonoquestions;
var noquestions =
cbonoquestions.options[cbonoquestions.selectedindex].value;
var cbotimelimit = document.frmquiz.cbotimelimit;
var timelimit = cbotimelimit.options[cbotimelimit.selectedindex].value;
window.top.fratopframe.fraglobalfunctions.resetquiz(noquestions,
timelimit);
window.location.href = "askquestion.htm";
}
</script>
cmdstartquiz_onclick()函数被连接到了cmdstartquiz按钮的onclick事件处理器,以便用户启动在线小测试程序。在上一版本的在线小测试程序中,仅仅调用了位于全局模块中的resetquiz()函数,并加载askquestion.htm页面。现在,我们需要获取用户在下拉列表框中选中的问题数量和时间限制。后面我们还将看到,resetquiz()函数也做出了相应的修改,以便接收两个参数—— 用户选择的问题数量和时间限制。
在cmdstartquiz_onclick()函数中,定义了变量cbonoquestions以引用表单中的cbonoquestions下拉列表框,cbonoquestions控件就是供用户选择回答多少个问题的下拉列表框。使用变量cbonoquestions可以避免对document对象和表单对象的冗长引用,使得代码保持简洁易读。
在cmdstartquiz_onclick()函数的第二行代码中,获取了cbonoquestions下拉列表框中所选中的值,即用户选择要回答多少个问题,并将该值保存在变量noquestions中。
随后的两行代码完成了类似的功能,用变量cbotimelimit来引用表单中的cbotimelimit下拉列表框,然后获取了cbotimelimit下拉列表框中所选中的值,即用户所选择的回答问题的时间限制,并将该值保存在变量timelimit中。
在接下来的那行代码中,复位了小测试程序,并将两个参数noquestions和timelimit传递给window.top.fratopframe.fraglobalfunctions.resetquiz()方法。其中,参数noquestions表示问题数量,参数timelimit表示时间限制。
这样就完成了对quizpage.htm页面的修改。将该页面进行保存后,即可关闭文本编辑器。
现在,我们将注意力转移到globalfunctions.htm页面,首先来看一下需要修改的resetquiz()函数,相应代码如下所示:
function resetquiz(numberofquestions, selectedtimelimit)
{
timeleft = selectedtimelimit;
totalquestionstoask = numberofquestions;
var indexcounter;
currentqnumber = -1;
questionsasked = new array();
for (indexcounter = 0; indexcounter < questions.length;indexcounter++)
{
questionsasked[indexcounter] = false;
}
numberofquestionsasked = 0;
numberofquestionscorrect = 0;
if (timeleft == -1)
{
window.status = "no time limit";
}
else
{
quiztimerid = window.setinterval("updatetimeleft()",1000);
}
}
首先修改的是resetquiz()函数的定义。在上一版本的在线小测试程序中,resetquiz()函数并不接收参数。现在,resetquiz()函数将接收两个参数,这两个参数分别表示问题数量和时间限制。
接着,将全局变量timeleft的值设置为参数selectedtimelimit的值,将全局变量totalquestionstoask的值设置为参数numberofquestions的值。在后面的代码中你将会看到,这两个全局变量将用以判断问题是否已经回答完毕,以及检查时间限制是否已经到点。
在resetquiz()函数的最后,添加了一个计时器,以监测剩余的时间。一种情况是计时器已经到点,剩余时间已经用完,即变量timeleft的值为–1。如果变量timeleft的值为–1时,则使用window对象的status属性,在浏览器的状态栏中显示一条时间到点的信息。注意,在netscape浏览器中,当框架页改变时,将在浏览器的状态栏中显示document:done以覆盖no time limit信息。如果变量timeleft的值不是–1,则使用setinterval()方法启动一个计时器,以每隔1s调用一次updatetimeleft()函数。
updatetimeleft()函数是一个新添加的函数。下面的代码用以创建updatetimeleft()函数。将该代码添加在脚本块其他函数的下面。
function updatetimeleft()
{
timeleft--;
if (timeleft == 0)
{
alert("time’s up");
numberofquestionsasked = totalquestionstoask;
window.top.fraquizpage.location.href = "askquestion.htm";
}
else
{
var minutes = math.floor(timeleft / 60);
var seconds = timeleft - (60 * minutes);
if (minutes < 10)
minutes = "0" + minutes;
if (seconds < 10)
seconds = "0" + seconds;
window.status = "time left is " + minutes + ":" + seconds;
}
}
updatetimeleft()函数完成了3个功能。首先,它将剩余时间减1,即timeleft--;然后判断是否还有剩余的时间,当剩余时间为0时,则停止小测试程序;否则,在浏览器的状态栏中显示剩余的时间,以便提示用户。
前面我们已经知道,当调用resetquiz()函数时,将复位在线小测试程序,并将全局变量timeleft设置为以秒为单位的时限值,在规定的时间内用户必须完成小测试。每隔1s将调用一次updatetimeleft()函数,在updatetimeleft()函数的第一行代码中,将剩余的时间减去1s:
timeleft--;
其后的if语句用以检查timeleft是否为0,即是否还有剩余时间。如果timeleft为0,则表示无剩余时间,这时将变量numberofquestionsasked的值设置为全局变量totalquestionstoask的值,即用户所选择的要回答问题的数量。接着,将页面导航到askquestion.htm页面,在该页面中将认为问题已经回答完毕并终止小测试程序,而不是继续提出一个新问题。
如果还有剩余时间,则该if语句的else子句将被执行,并更新浏览器的状态栏,以显示剩余的分钟数和秒数。
这里,需要将timeleft中保存的以秒为单位的时间值拆分成分钟数和秒数。首先,可以使用下面这行代码获取分钟数的值:
var minutes = math.floor(timeleft / 60);
上面的代码将返回变量timeleft中保存的总秒数除以60的商的整数部分,这正是我们所需要的分钟数。而下面的代码则用以获得秒数:
var seconds = timeleft - (60 * minutes);
在上面的代码中,用总的秒数timeleft减去分钟数所对应的秒数,即可得到除去分钟数之后剩余的秒数。例如,如果timeleft是61,则分钟数为:
minutes = 61 / 60 = 1.01667
取整后将返回整数1,表示1分钟,而剩余的秒数为:
seconds = 61 - (60 * 1) = 1
我们希望按“分钟:秒钟”的格式将剩余时间显示在浏览器的状态栏中,例如对于上面的例子,希望将剩余时间显示为01:01。但是,当分钟或者秒钟的值小于10时,把分钟和秒钟的字符串连接起来将是1:1这样一个字符串。对于在线小测试程序,分钟数不会超过5,实际上只需直接在前面加上0即可。但是,为了使代码能适应未来需求发生的变化—— 例如允许用户回答问题的时间超过9分钟,则应使用if语句进行检查,以便确定分钟数是否小于10。
要修正格式问题,只需在分钟数或秒钟数小于10时,在其前面添加一个额外的0即可,相应代码如下所示:
if (minutes < 10)
minutes = "0" + minutes;
if (seconds < 10)
seconds = "0" + seconds;
最后,更新浏览器状态栏中剩余时间的显示:
window.status = "time left is " + minutes + ":" + seconds;
在前面的这两个函数中,我们用到了几个新的全局变量。这些全局变量为:
var timeleft =-1;
var totalquestionstoask = 0;
var quiztimerid = 0;
请将上面全局变量的定义添加到脚本块的开始处。
最后,再对getquestion()函数进行两处较小的修改,就能完成本章中小测试程序的修改。
首先,修改的是函数开始处的if语句:
if (totalquestionstoask != numberofquestionsasked)
{
var questionnumber = math.floor(math.random() * questions.length);
在上一版本的在线小测试程序中,只要可用的问题还没有问完,就可以继续提问。现在,当变量totalquestionstoask的值不等于实际所问问题的数量时,则继续进行提问。totalquestionstoask是一个全局变量,其中保存的是用户在下拉列表框中选中的问题的数量。在前面的代码中,用户选中的问题数量将作为参数传递给resetquiz()函数,并在resetquiz()函数中赋值给全局变量totalquestionstoask。
第二个修改的地方是else子句。当小测试结束时,将把用户小测试结果的汇总信息输出到页面上。注意,在前面的resetquiz()函数中,我们设置了一个计时器以监测剩余时间,当时间到点时就结束在线小测试程序。现在,当小测试程序结束时,应该使用clearinterval()方法清除该计时器。当计时器启动时,该计时器的id号已经保存在全局变量quiztimerid中,只需将该计时器的id号传递给clearinterval()方法,即可清除该计时器。另外,当用户并未设置答题的时限时,即用户未在cbotimelimit下拉列表框中选择一个时限时,则timeleft的值将为–1,这时,前面的resetquiz()函数中并未设置任何计时器,因此,这里也就无须对计时器进行清除。为此,在下面的代码中,使用了if (timeleft != –1)进行判断:
currentqnumber = questionnumber;
questionsasked[questionnumber] = true;
}
else
{
if (timeleft != -1)
{
clearinterval(quiztimerid);
}
questionhtml = "<h3>quiz complete</h3>";
questionhtml = questionhtml + "you got" + numberofquestionscorrect;
到此为止,所有的修改都已经完成了。将上面修改后的代码保存为globalfunctions.htm文件。并在浏览器中加载triviaquiz.htm页面,以启动在线小测试程序。
如果修改后的代码正常,我们将看到一个如图9-8所示的页面。
图 9-8
如果在time limit下拉列表框中选择了一个时限,并单击start quiz按钮,则第一个随机抽取的问题将显示在页面上,并且计时器将开始倒计时,在浏览器的状态栏中将显示剩余的时间。
在firefox浏览器和ie 7版本的浏览器中,通过javascript修改浏览器状态栏的功能在默认情况下是被禁止的。要在firefox浏览器中打开该功能,只需选择tools | options,然后选择content标签页。然后,单击advanced options按钮,然后选中change status bar text复选框。对于ie 7浏览器,只需选择tools | internet options,然后再选择security标签页。单击internet,然后单击custom level,在打开的窗口中将滚动条下拉到allow status bar updates via script复选框,并选中该复选框。
本章中对“在线小测试”程序的修改就到这里。在第11章中,我们将再次回到“在线小测试”程序,以介绍如何使用cookie将信息保存在用户的计算机上,以便提供一个前面所答题目信息的表格。
新闻热点
疑难解答