javascript: alert("blah");
在地址栏中,弹出的警报框会暂停我的计时器。在测验中这是非常不希望的。
我认为没有办法阻止这种行为……但我还是要问一下。
如果确实如此,你能建议我应该怎么做吗?
javascript: alert("blah");
永远不要依赖JavaScript(或任何其他客户端时间)来计算在postbacks或不同页面之间进行的操作的经过时间。
如果您始终比较服务器日期,则很难被人欺骗:
不,无法阻止JavaScript中单个线程的警报。可以使用其他方式进行用户通知,例如浮动层。
显然,预览渲染与发布渲染不同。此段落旨在确保接下来的两行显示为代码。
// Preserve native alert() if you need it for something special
window.nativeAlert = window.alert;
window.alert = function(msg) {
// Do something with msg here. I always write mine to console.log,
// but then I have rarely found a use for a real modal dialog,
// and most can be handled by the browser (like window.onbeforeunload).
};
这是一个模态框,会暂停执行。考虑使用不会暂停执行的替代方法,比如Lightbox技术。
对SyaZ的问题的反馈循环澄清了所涉及的问题。
以下是总结迄今为止好的答案的尝试:
客户端脚本天生容易被操纵以作弊在线测验。请参见@Filini的服务器端方法
window.alert = function(msg) {}将覆盖alert(),可能会击败低效果的放在地址栏中:javascript:alert('暂停页面,以便我可以谷歌答案')或者我现在要使用我的“打电话给朋友”。 参见Courtesy of @eyelidlessness
如果必须使用客户端方法,而不是使用setTimeOut(),您可以使用一个自定义日期比较的暂停函数,如此(concept by @Mnebuerquo,code example by me (@micahwittman)):
例如:
var beginDate = new Date();
function myTimeout(milsecs){
do { curDate = new Date(); }
while((curDate-beginDate) < milsecs);
}
function putDownYourPencils(milsecs){
myTimeout(milsecs);
var seconds = milsecs / 1000;
alert('Your ' + seconds + ' seconds are up. Quiz is over.');
}
putDownYourPencils(3000);
最终,您不能信任用户输入。如果没有在服务器上跟踪经过的时间,就无法保证数据没有被篡改。
然而,如果您确信您的测验参与者不精通JavaScript,并且仅仅依靠他们在某个地方发现的“诀窍”,您可以使用以下代码测试作弊(暂停),这不需要修改window.alert:
var timer = {
startDatetime: null,
startSec: 0,
variance: 1,
exitOnPause: true,
count: function (config) {
var that = this;
if (typeof config == "object" && typeof parseInt(config.seconds) == "number" && !isNaN(parseInt(config.seconds)))
{
if (typeof parseFloat(config.variance) == "number" && !isNaN(parseFloat(config.variance))) this.variance = config.variance;
if (typeof config.exitOnPause == "boolean") this.exitOnPause = config.exitOnPause;
if (config.seconds > 0)
{
if (!this.startSec) this.startSec = config.seconds;
if (!this.startDatetime) this.startDatetime = new Date();
var currentDatetime = new Date();
if (currentDatetime.getTime() - this.startDatetime.getTime() > (this.startSec - config.seconds) * this.variance * 1000)
{
if (typeof config.onPause == "function") config.onPause();
if (!this.exitOnPause)
{
this.startDatetime = new Date();
this.startSec = config.seconds--;
window.setTimeout(function () { that.count(config); }, 1000);
}
}
else
{
config.seconds--;
window.setTimeout(function () { that.count(config); }, 1000);
}
}
else
{
if (typeof config.onFinish == "function") config.onFinish();
}
}
}
};
这个计时器对象只有一个方法,count(),接受一个对象作为输入。它期望输入对象中至少有一个seconds属性。
出于某种原因,window.setTimeout并不总是按预期工作。有时,在我的机器上,应该在1秒后执行代码的window.setTimeout(x, 1000)需要2秒以上的时间。因此,在这种情况下,您应该允许一定的变化范围,以便那些没有作弊的人不会被标记为作弊者。变化范围默认为1,但可以在输入对象中进行覆盖。以下是如何使用此代码的示例,它允许慢速用户有2.5秒的“摇晃空间”:
timer.count({
seconds: 10,
onPause: function () { alert("You cheated!"); window.location.replace("cheatersAreBad.html"); },
onFinish: function () { alert("Time's up!"); },
variance: 2.5
});
使用这样的解决方案,您可以使用Ajax告诉服务器端脚本用户已暂停计时器或重定向用户到一个页面,说明他们被抓到作弊了。如果出于某种原因,您想允许用户在被抓到作弊后继续参加测验,则可以将exitOnPause设置为false:
timer.count({
seconds: 10,
exitOnPause: false,
onPause: function () { recordCheaterViaAjax(); },
onFinish: function () { alert("Time's up!"); },
variance: 2.5
});