2015-04-02 48 views
3

我有一个简单的测验形式与几个输入和选择,我需要测量参赛者写/选择答案的时间。测量时间为输入

这就是我想要的,但它报告不正确的时间:

$('input, select').on('focus', function(event) { 
 

 
    el = $(this); 
 

 
    name = el.attr('name'); // console.log(name); 
 
    a = performance.now(); 
 
    a_value = el.val(); 
 

 
    console.log(name + ' focused.'); 
 

 
    $(el).on('input select cut copy paste', function(event) { 
 
     console.log('el: ' + el); 
 
     b_value = el.val(); 
 
     if (a_value != b_value) { 
 
      b = performance.now(); 
 
      if (name in times) { 
 
       console.log('exists'); 
 
       times[name] = times[name] + (b - a); 
 
      } else { 
 
       times[name] = b - a; 
 
      } 
 
     } 
 
    }); 
 

 
    $(el).on('blur', function(event) { 
 
     alert(times); 
 
    }); 
 

 
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 
<!DOCTYPE html> 
 
<html> 
 
<head> 
 
    <meta charset="utf-8"> 
 
    <title>JS Bin</title> 
 
</head> 
 
<body> 
 

 
    <input type="text" name="" id=""> 
 
    <select name="" id=""> 
 
    <option value="">option1</option> 
 
    <option value="">option2</option> 
 
    </select> 
 
    
 
</body> 
 
</html>

+0

我想你可以使用这个[问题](http://stackoverflow.com/questions/6626044/how-to-monitor-time-it-takes-a-user-to-enter-data-into-a -input-text-field-in-htm?answertab = active#tab-top) – FiN 2015-06-23 07:18:42

+1

if(times in times)是什么时间?它在控制台中未定义。 – AngularHarsh 2015-06-23 07:27:27

+0

请修正片段 – 2015-06-23 07:37:32

回答

2

在与您交谈(OP)后,我对您的基本代码进行了一些调整。

首先,.on('input ...')在每次窗体元素具有焦点时被调用,以便事件处理程序进行堆叠。在模糊处理程序中调用相应的.off('input ...')来处理此问题。

接下来,为了在JavaScript中创建一个关联数组,我们通常使用对象,所以我制作了times = {}

接下来,times[name] = times[name] + (b - a);在元素首次聚焦时始终使用来自a的初始时间值,因此聚合时间快速累积。之后我们可以通过设置a = b;来弥补这一点。最后,当选择发生变化时,为了跟踪输入变化的时间,我们可以更新内部选定值,如a_value = b_value;

我希望这是你在找什么。

var times = {}; 
 
$('input, select').on('focus', function(event) { 
 
    var el = $(this); 
 

 
    // This will get the name of the input or select. Is that right? 
 
    // OP: yes, this becomes the key in the array 
 
    var name = el.attr('name'); 
 
    var a = performance.now(); 
 
    var a_value = el.val(); 
 

 
    // This will attach an event handler over and over unless we 
 
    // unattach it. Please see "blur" below 
 
    el.on('input select cut copy paste', function(event) { 
 
    var b_value = el.val(); 
 

 
    // Initial values are updated as inputs change 
 
    // so the times don't stack up 
 
    if (a_value !== b_value) { 
 
     b = performance.now(); 
 
     if (times.hasOwnProperty(name)) { 
 
     console.log('exists'); 
 
     times[name] = times[name] + (b - a); 
 
     a = b; 
 
     } else { 
 
     console.log('adding ' + name); 
 
     times[name] = b - a; 
 
     } 
 
     a_value = b_value; 
 
    } 
 
    }); 
 

 
    el.one('blur', function(event) { 
 
    console.dir(times); 
 

 
    // Update the times display 
 
    displayTimes(); 
 

 
    // Unattach the event handler added in on("focus") 
 
    el.off('input select cut copy paste'); 
 
    }); 
 

 
    // For the demo 
 
    function displayTimes() { 
 
    // Output results 
 
    var str = ""; 
 
    $.each(times, function(key, value) { 
 
     str += key + " total time: " + value + "<br>"; 
 
    }); 
 
    $("#results").html(str); 
 
    } 
 

 
    // Periodically update the times just for the demo 
 
    setInterval(displayTimes, 200); 
 
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 
<input type="text" name="input" id=""> 
 
<select name="select" id=""> 
 
    <option value="option1">option1</option> 
 
    <option value="option2">option2</option> 
 
</select> 
 
<div id="results"></div>

+1

太棒了!虽然它的效果很好,但我认为我会用tock.js来启动,暂停,停止和停止计时器,因为我会处理太多事情。谢谢你,虽然! – 3zzy 2015-06-24 08:41:01

1

试试这个..

<script> 
    var Stopwatch = (function() { 
      var s; 
      return { 
       settings: { 
        stop: 0, 
        sw: document.querySelectorAll(".stopwatch")[0], 
        results: document.querySelectorAll(".results")[0], 
        mills: 0, 
        secs: 0, 
        mins: 0, 
        i: 1, 
        times: ["00:00:00"], 
        clearButton: "<a href=\"#\" class=\"button\" onClick=\"Stopwatch.clear();\">Clear</a>" 
       }, 
       init: function() { 
        s = this.settings; 
        setInterval(this.timer, 1); 
       }, 
       clear: function() { 
        s.i = 1, 
        s.times = ["00:00:00"], 
        s.results.innerHTML = s.clearButton; 
       }, 
       lap: function() { 
        if (s.i === 1) { 
         s.results.innerHTML = s.clearButton; 
        } 
        s.times.push(("0" + s.mins).slice(-2) + ":" 
             + ("0" + s.secs).slice(-2) + ":" 
             + ("0" + s.mills).slice(-2)); 
        var diffTime = ("0" + Math.floor(s.times[s.i].split(":")[0] 
              - s.times[s.i-1].split(":")[0])).slice(-2) 
              + ":" 
              + ("0" + Math.floor(s.times[s.i].split(":")[1] 
              - s.times[s.i-1].split(":")[1])).slice(-2) 
              + ":" 
              + ("0" + (s.times[s.i].split(":")[2] 
              - s.times[s.i-1].split(":")[2])).slice(-2); 
        s.results.innerHTML = s.results.innerHTML + "<tr><td>" 
                  + s.times[s.i] + "</td><td>" 
                  + diffTime + "</td></tr>"; 
        s.i++; 
       }, 
       restart: function() { 
        s.mills = 0, 
        s.secs = 0, 
        s.mins = 0; 
        this.start(); 
       }, 
       start: function() { 
        s.stop = 0; 
       }, 
       stop: function() { 
        s.stop = 1; 
       }, 
       timer: function() { 
        if (s.stop === 0) { 
         if (s.mills === 100) { 
          s.secs++; 
          s.mills = 0; 
         } 
         if (s.secs === 60) { 
          s.mins++; 
          s.secs = 0; 
         } 
         s.sw.innerHTML = ("0" + s.mins).slice(-2) + ":" 
                + ("0" + s.secs).slice(-2) + ":" 
                + ("0" + s.mills).slice(-2); 
         s.mills++; 
        } 
       } 
      }; 
     })(); 
$('.textbox,.selectbox').focusin(function(event) { 
Stopwatch.init(); 
Stopwatch.restart();  
}); 
$('.textbox,.selectbox').on('blur', function(event) { 
    Stopwatch.stop(); 
}); 

Working Fiddle Here

References

+0

不完全是我想要的,但秒表参考很有帮助,谢谢! – 3zzy 2015-06-23 10:29:08

0

你可以在this fiddle找到我试过的。 对我来说,主要的一点是,你一次又一次地累加了一次,因为最初的时间没有变化,并且你多次添加了应答时间。

if (name in times) { 
    console.log('exists'); 
    times[name] = times[name] + (b - a); 
    //here you already had added (b1 - a) with b1 < b 
    //either you reset 'a' here or you store the diff in a variable and sum it up at the end 
} else { 
    times[name] = b - a; 
} 

我储存的解答时间在一个变量并添加到阵列上blur,并试图尽可能地与你原来的方法,因为相一致。

虽然我仍然怀念一些事情。这主要与作弊有关。就我而言,你只需要计算真实的变化时间(从focus到最后的input,也就是说,不包括从最后的inputblur的时间,并且绝对不是查看页面的时间,并且可能在写字板环境)。

在一个公平和安全的系统中,你应该,恕我直言,考虑一下人们可以看到测验的时间超过他/她实际上正在写答案的时间。但这显然取决于测验的结果!

1

我做了简单的jQuery插件这一点。它能够告诉你什么是总编辑时间(仅当实际使用编辑时),首先编辑任何输入元素的时间和最后编辑时间。您还可以获取所有编辑时间。

(function() { 
    var getTime = function() { return performance.now(); }; 
    function MeasureTime() { 
     this.editTimes = []; 
     this.currentEdit = null; 
     this.lastEdit = {start:0, last: 0}; 
     this.firstEdit = 0; 
    } 
    MeasureTime.prototype = { 
     setFirst: function() { 
      this.firstEdit = getTime(); 
      this.setFirst = new Function(); 
     }, 
     startEdit: function (val) { 
      this.setFirst(); 
      if(this.currentEdit == null) { 
       this.currentEdit = {start: getTime(), last: getTime(), value: val}; 
       this.editTimes.push(0); 
      } else { 
       this.edit(val); 
      } 
     }, 
     edit: function (val) { 
      if(this.currentEdit == null) 
        this.startEdit(val); 
      else { 
       var current = this.currentEdit; 
       if(current.value == val) 
        return; 
       current.last = getTime(); 
       this.editTimes.pop(); 
       this.editTimes.push(current.last - current.start); 
      } 
     }, 
     stopEdit: function() { 
      if(this.currentEdit != null) { 
       this.lastEdit = this.currentEdit; 
       this.currentEdit = null; 
      } 
     }, 
     getEvent: function() { 
      return new TimeMeasuredEvent(this.editTimes, this.currentEdit || this.lastEdit, this.firstEdit); 
     } 
    }; 
    function TimeMeasuredEvent (all, current, first) { 
     this.all = all.slice(0); 
     this.start = current.start; 
     this.last = current.last; 
     this.first = first; 
    } 
    TimeMeasuredEvent.prototype = { 
     current: function() { 
      return this.all[this.all.length-1]; 
     }, 
     total: function() { 
      var sum = 0, a = this.all, l = a.length, i = -1; 
      while(++i<l) 
       sum+=a[i]; 
      return sum; 
     } 
    }; 
    function EnsureMeasureTime() { 
     if (typeof(this.measureTimeData) === "undefined") { 
      var mtd = this.measureTimeData = new MeasureTime(); 
      $(this).on('focus', function() { 
       mtd.startEdit(this.value); 
     $(this).on('input.measuretime select.measuretime cut.measuretime copy.measuretime paste.measuretime', function() { 
      mtd.edit(this.value); 
      $(this).trigger('timeMeasured', [mtd.getEvent()]); 
     }); 
      $(this).on('blur', function() { 
       mtd.stopEdit(); 
       $(this).trigger('timeMeasured', [mtd.getEvent()]); 
       $(this).off('measuretime'); 
      }); 
     }); 
     } 
    } 
    $.fn.measureTime = function() { 
     $(this).each(EnsureMeasureTime); 
     return this; 
    }; 
})(); 

使用范例(fiddle):

var inputs = $('input, select'); 
inputs.measureTime(); 
var all = {}; 
inputs.on('timeMeasured', function (ev, data) { 
    console.log(ev, data); 
    all[ev.target.name] = data.total(); 
    console.log("First edit time: " + data.first); 
    console.log("Last edit time: " + data.last); 
    console.log("All edits durations: " + data.all.join(", ")); 
    console.log("Current edit duration: " + data.current()); 
    console.log("Total edit duration: " + data.total()); 
    var s = ""; 
    for(var n in all) { 
     s+= n + ": " + all[n]+"\n"; 
    } 
    $("#times").text(s); 
}); 

您还可以通过访问element.measureTimeData原料MeasureTime对象来获取编辑倍。