Inhaltsverzeichnis

LatencyTimer

The JavaScript class LatencyTimer is designed to help you measure response times in the questionnaire.

Tip: Take a look at the question types beforehand Selection Sequence and Assignment. These automatically record the response time.

The measurement of reaction times is based on JavaScript in the Questionnaire, that is, program code that runs in the respondent's browser. This program code can react to input from the respondents, for example, mouse clicks or keyboard strokes. These trigger so-called JavaScript events.

DThe goal of the LatencyTimer class is now to measure the difference between such events. You can expect an accuracy <100 ms when measuring reaction times using JavaScript. For the difference between two events accordingly with an accuracy <200 ms.

Preparation

Make the library available on the corresponding page in the questionnaire using library().

library('LatencyTimer');

Furthermore, you require Internal Variables on the questionnaire page. In fact, as many as you want to measure different reaction times. Drag the corresponding question of type “internal variables” to the questionnaire page.

Reference

Timer-Instanz

The following methods are available for an instance of the LatencyTimer class. Some parameters are used here again and again:

void latencyTimer.registerElement(Element element, mixed storage, boolean storeFirst)

With registerElement() the reaction time to click on an HTML-element element is recorded.

void latencyTimer.registerItem(SoSciTools.QuestionItem|Question item, mixed storage, boolean storeFirst, mixed multiStore)

With registerItem() the reaction time to answer a (selection) question or an item in a set of questions is recorded.

void latencyTimer.registerRadio(String prefix, mixed storage, boolean storeFirst)

With registerRadio() the reaction time to click on radio buttons is distinguished, which use the given prefix and a serial number. For example, the prefix “SK01_01” would monitor the radio buttons “SK01_011”, “SK01_012” and so on. Most of the time it is easier to use latencyTimer.registerItem().

void latencyTimer.registerSelection(String auswahlID, mixed storage, boolean storeFirst)

With registerSelection() the reaction time to click on a simple selection question with the identifier selectionID is recorded. Most of the time it is easier to use latencyTimer.registerItem().

void latencyTimer.registerSlider(String sliderID, mixed storage, boolean storeFirst, mixed multiStore)

With registerSlider() the reaction time for selecting a value on a slider is recorded. Since the value on a slider may be changed again, it is necessary to specify in multiStore where further changes to the value are to be stored.

Function latencyTimer.eventHandler(mixed storage, boolean storeFirst, mixed multiStore)

The method eventHandler() returns a function which can be used directly in Element.addEventListener(). This way reaction times can also be stored for events that are not clicks.

Static Methods

The following methods are available regardless of the instance.

Element LatencyTimer.getInternal(string FrageKennung, int VariablenNummer)

By means of getInternal() an internal variable can be accessed.

In most cases it is easier to use s2.FrageKennung.item(VariablenNummer) .

Application

The LatencyTimer library is based on forming pairs of (1) items, questions or choice fields and (2) internal variables. Whenever an item etc. is clicked, the LatencyTimer then stores the time (in milliseconds) that has passed since the last click on another item. The crux of this is that you need a preceding click as a reference.

Hint: Optionally, you can also allow the time since the page was loaded to be used as a reference. However, your first measurement then includes reading the question, etc., so it is significantly distorted compared to the other measurements.

The actual use now is to create an instance of LatencyTimer using new LatencyTimer() and then define pairs of input option and internal variable. The functions available for this are listed below. For a scale “SK01” with 10 items, and storing the reaction times into the 10 variables of the internal variable question “IV01” the code could look like this:

<script type="text/javascript">
window.addEventListener("load", function() {
    var timer = new LatencyTimer();
    for (var i=1; i<=10; i++) {
        var item = s2.SK01.item(i);
        var internal = s2.IV01.item(i);
        timer.registerItem(item, internal);
    }
}
</script>

By window.addEventListener("load", ...) this code is executed only when the page is fully loaded. At this point the scale can be addressed via s2.SK01 and the internal variables s2.IV01.

This example uses the LatencyTimer.registerItem() method, which uses the internal representation of the items in SoSci Survey (JavaScript Library SoSciTools). This way you don't have to search for the selection fields of the scale one by one.

Instead of counting in the FOR loop, you can also query the items directly from the object representing the scale.

window.addEventListener("load", function() {
    var timer = new LatencyTimer();
    for (var key in s2.SK01.items) {
        var item = s2.SK01.items[key];
        var itemID = item.id
        var internal = s2.IV01.item(item.id);
        timer.registerItem(item, internal);
    }
}

Selection Questions

In this example, the clicks on three selection questions (simple selection) “AF01”, “AF02” and “AF03” are to be saved.

window.addEventListener("load", function() {
    var timer = new LatencyTimer();
    timer.registerItem(s2.AF01, "IV01_01");
    timer.registerItem(s2.AF02, "IV01_02");
    timer.registerItem(s2.AF03, "IV01_03");
}

Here the internal variables are addressed by their identifier – of course s2.IV01.item(1) would be just as possible.

If reaction time is also to be recorded when respondents change their mind, two internal variables are required per choice question.

window.addEventListener("load", function() {
    var timer = new LatencyTimer();
    timer.registerItem(s2.AF01, "IV01_01", false, "IV01_02");
    timer.registerItem(s2.AF02, "IV01_03", false, "IV01_04");
    timer.registerItem(s2.AF03, "IV01_05", false, "IV01_06");
}

In the first variable the reaction time for the first click is stored. In the second variable the total reaction time (incl. that for the first click) is stored.

Record other events

The eventHandler() method allows storing reaction times for arbitrary events.

<div id="button01" style="width: 50px; height: 20px; border: 1px solid red; display: inline-block"></div>
<div id="button02" style="width: 50px; height: 20px; border: 1px solid blue; display: inline-block"></div>
 
<script type="text/javascript">
window.addEventListener("load", function() {
    var timer = new LatencyTimer();
    document.getElementById("button01").addEventListener("click", timer.eventHandler("IV01_01"));
    document.getElementById("button02").addEventListener("click", timer.eventHandler("IV01_02"));
});
</script>

The method eventHandler() can also be used to record the reaction times of an open text input field (in the example “OT01_01”) until the first and until the last keystroke.

window.addEventListener("load", function() {
    var timer = new LatencyTimer();
    document.getElementById("OT01_01").addEventListener(
        "keydown",
        timer.eventHandler("IV01_01", false, "IV01_02")
    );
});

If you want to realize this recording for a larger number of input fields, it is useful to create two questions of the type “internal variables”, one (in the example “IV01”) for the first, one for the last keystroke (“IV02”).

window.addEventListener("load", function() {
    var timer = new LatencyTimer();
    for (var key in s2.OT01.items) {
        var item = s2.OT01.items[key];
        var itemID = item.id;
        var internalA = s2.IV01.item(itemID);
        var internalB = s2.IV02.item(itemID);
        item.input.addEventListener(
            "keydown",
            timer.eventHandler(internalA, false, internalB)
        );
    }
});