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>
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>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With