Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Measuring time for input

I have a simple quiz form with several inputs and selects, and I need to measure the time it took the contestant to write/choose an answer.

This is what I'm trying, but it reports incorrect time:

$('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>
like image 830
eozzy Avatar asked Dec 06 '25 11:12

eozzy


1 Answers

After talking with you (the OP), I've made several adjustments to your base code.

First, the .on('input ...') was being called every time the form element had focus so event handlers were stacking up. A corresponding .off('input ...') is called in the blur handler to handle this.

Next, to make an associative array in JavaScript we normally use objects, so I made times = {}.

Next, times[name] = times[name] + (b - a); keeps using the initial time value from a when the element was first focused, so aggregated time stacks up quickly. We can compensate for this by setting a = b; afterwards.

Finally, to keep track of when a select changes much like when the input changes, we can update the internal selected value like a_value = b_value; when the selection has changed.

I hope this is what you are looking for.

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>
like image 92
Drakes Avatar answered Dec 07 '25 23:12

Drakes



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!