Moving window code component not working

URL of experiment:

Description of the problem: Hello everyone!
I have built an experiment in the Builder and attached a code component to some routines. The experiment is a moving window self-paced reading task.
Although it runs smoothly when I run it on PsychoPy, I’ve been facing some issues while trying to run it online.
Since I don’t know much (anything at all, actually) about programming languages, I talked to a developer who translated the codes of the code component so I could start from somewhere. We’ve been trying to get it to run online for the past days, and yet, nothing works.

I honestly have no clue what to do next. If anyone can shed some light, I’d be very thankful for anything, really!

There are basically 2 code in the components (that repeat on some other routines, changing the text component they associate with as well as the column in the xlsx file).

The begin routine:

sentenceTREINOList = sentenceTREINO.split(’/’)
#this breaks your sentence’s single string of characters into a list of individual
#words, e.g. ‘The quick brown fox.’ becomes [‘The’, ‘quick’, ‘brown’, ‘fox.’]

#keep track of which word we are up to:
wordNumber = -1 # -1 as we haven’t started yet

#now define a function which we can use here and later on to replace letters with ‘x’:

def replaceWithX(textList, currentWordNumber):

xSentenceTREINO = ''
for index, word in enumerate(textList): # cycle through the words and their index numbers
    if index != currentWordNumber:
        xSentenceTREINO = xSentenceTREINO + '_' * len(word) + ' ' # add a string of x characters
        xSentenceTREINO = xSentenceTREINO + word + ' ' # except for the current word

return xSentenceTREINO # yields the manipulated sentence


var setenceTREINOlist = sentenceTREINO.split(’/’);

var wordNumber = -1;

function replaceWithX(textList,current){
var xSetenceTREINO = ‘’;
var index = 0;
for(word in Object.values(textList)){

    if(index != currentWordNumber){
        xSetenceTREINO = '_' *  word.length + ' ';   
        xSentenceTREINO = xSentenceTREINO + word + ' ';
    index = index+1;
return xSentenceTREINO;


And the each frame:

#now at the very beginning of the trial, we need to run this function for the
#first time. As the current word number is -1, it should make all words ‘x’.
#Use the actual name of your Builder text component here:

text_10.text = replaceWithX(sentenceTREINOList, wordNumber)

#In the Builder interface, specify a “constant” value for the text content, e.g.
#‘test’, so it doesn’t conflict with our code.

keypresses = event.getKeys() # returns a list of keypresses

if len(keypresses) > 0: # at least one key was pushed

if 'space' in keypresses:

    thisResponseTime = t # the current time in the trial
    wordNumber = wordNumber + 1
    if wordNumber < len(sentenceTREINOList):

        if wordNumber == 0: # need to initialise a variable:
            timeOfLastResponse = 0

        # save the inter response interval for this keypress,
        # in variables called IRI_0, IRI_1, etc:
        thisExp.addData('IRI_TREINO_' + str(wordNumber), thisResponseTime - timeOfLastResponse)
        timeOfLastResponse = thisResponseTime

        # update the text by masking all but the current word
        text_10.text = replaceWithX(sentenceTREINOList, wordNumber)
        continueRoutine = False # time to go on to the next trial

elif 'escape' in keypresses:

    core.quit() # I think you'll need to handle quitting manually now.


text_10.text = replaceWithX(sentenceTREINOList, wordNumber)

var keypresses= event.getKeys();

if (keypresses.lenght > 0){

    thisResponseTime = t ;
    wordNumber = wordNumber + 1;
    if (wordNumber < sentenceTREINOList.lenght){
        if (wordNumber == 0){ 
            timeOfLastResponse = 0;
        thisExp.addData('IRI_TREINO_' + str(wordNumber), thisResponseTime - timeOfLastResponse)
        timeOfLastResponse = thisResponseTime;
        text_10.text= replaceWithX(sentenceTREINOList, wordNumber)
        continueRoutine = False 
else if (keypresses.include('escape')){


I have found that setting a Builder component to update every frame doesn’t work. You should set it to constant and then update it in the code.

Have a look at my crib sheet

Best wishes,


Thanks for your reply, Wakefield.
The component in builder is already set as constant.
The each frame above refers to code in the code component of the routine.

Did you get someone to manually translate the code to JavaScript? If so, then I’m probably not going to be able to help, since I’m learning errors causes by imperfections in the auto translate.

Also, you haven’t actually said what error you are getting, which is why I gave very generic advice.

Yes, Wakefield. Someone manually translated it for me. Thanks for trying to help anyway!
So far I am getting the following error:

… is not defined usually means that you need to give the variable a value (or specify it as empty) at the start of the experiment. You can’t just create it for the first time in the routine when you want it.

Best wishes



During the last days I’ve been trying to run a Self-Paced Moving Window experiment, very similar to the one @matheusba presented. Instead of using the code he wrote on his post, I used PsychoPy to convert the Python Script into JavaScript (with some corrections to the Python Code @matheusba presented).

I also added the code component @wakecarter suggests in his Crib Sheet (thanks!) at the beginning of the experiment. However, I still get the same error as @matheusba.

When I try to run the experiment online (here), I get exactly the same error: it does not recognize the function replaceWithX(), and I’ve tried to copy it to the beginning of the experiment, as suggested by @wakecarter, and it also didn’t work.

When I run the experiment on my computer, using PsychoPy (with JS code) it does not work but the problem seems to be different: I believe that the stimulus file is not properly uploaded.

Does anyone have any suggestion that could help us with this problem?

Thank you in advance!


Hi everyone,

Just to tell to anyone that might be interested in this topic that I had some help and the solution is as follows:

  1. in the component code, in Begin Routine tab add:
sentenceTREINOList = sentenceTREINO.split("/");
wordNumber = (-1);
  1. in Each Frame tab add:
var _pj;
function replaceWithX(textList, currentWordNumber) {
    var index, result, word;
    result = "";
    index = 0;
    while ((index < textList.length)) {
        word = textList[index];
        if ((index !== currentWordNumber)) {
            result = ((result + ("_".repeat(word.length))) + " ");
        } else {
            result = ((result + word) + " ");
        index = (index + 1);
    return result;
function _pj_snippets(container) {
    function in_es6(left, right) {
        if (((right instanceof Array) || ((typeof right) === "string"))) {
            return (right.indexOf(left) > (- 1));
        } else {
            if (((right instanceof Map) || (right instanceof Set) || (right instanceof WeakMap) || (right instanceof WeakSet))) {
                return right.has(left);
            } else {
                return (left in right);
    container["in_es6"] = in_es6;
    return container;
_pj = {};
text_10.text = replaceWithX(sentenceTREINOList, wordNumber);
keypresses = event.getKeys();
if ((keypresses.length > 0)) {
    if (_pj.in_es6("space", keypresses)) {
        thisResponseTime = t;
        wordNumber = (wordNumber + 1);
        if ((wordNumber < sentenceTREINOList.length)) {
            if ((wordNumber === 0)) {
                timeOfLastResponse = 0;
            thisExp.addData(("IRI_TREINO_" + wordNumber.toString()), (thisResponseTime - timeOfLastResponse));
            timeOfLastResponse = thisResponseTime;
            text_10.text = replaceWithX(sentenceTREINOList, wordNumber);
        } else {
            continueRoutine = false;
    } else {
        if (_pj.in_es6("escape", keypresses)) {

As mentioned on the previous post, I also added the code component @wakecarter suggests in his Crib Sheet at the beginning of the experiment.

Now the experiment runs perfectly in Pavlovia.

Thank you very much.