SPR Moving Window: Display multi-word region on click but still keep spaces between individual words

Hello all!
I’m working on a Self-paced Reading task with a Moving window design where all words in a sentence are initially covered by dashes until the participant presses space and the first region (with multiple words) displays. Once they click again, that first region will be covered by dashes again and the second region will be displayed and so on.
Below is my JS code component to achieve this. I’ve put commas between regions in my csv and coded sentenceList to split based on those commas. This way, rather than regions being word by word, it’ll be region by region which can contain multiple words.

Begin Routine:

sentenceList = Sentence.split(",");
wordNumber = (- 2);

Each Frame:

var _pj;
function replaceWithdash(sentenceList, currentWordNumber) {
    var index, result, word;
    result = "";
    index = 0;
    while ((index < sentenceList.length)) {
        word = sentenceList[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 = {};
Trials_Display.text = replaceWithdash(sentenceList, wordNumber);
keypresses = psychoJS.eventManager.getKeys();
if ((keypresses.length > 0)) {
    if (_pj.in_es6("space", keypresses)) {
        thisResponseTime = t;
        wordNumber = (wordNumber + 1);
        if ((wordNumber < sentenceList.length)) {
            if ((wordNumber === 0)) {
                timeOfLastResponse = 0;
            thisExp.addData(("IRI_" + wordNumber.toString()), (thisResponseTime - timeOfLastResponse));
            timeOfLastResponse = thisResponseTime;
            Trials_Display.text = replaceWithdash(sentenceList, wordNumber);
        } else {
            continueRoutine = false;
    } else {
        if (_pj.in_es6("escape", keypresses)) {

My problem comes with the display of the dashes. Like I said, I define the regions using commas, so in the replaceWithdash function defined above, I was able to basically say ‘cover regions with the same amount of dashes as their length and then put a space after that’. With that code, this is the display:

------  ---  ------
The dog  ---  ------

Notice there is a space between regions (so here there would be three regions), but there’s no space between the words in those regions when they are all dashes

However, my goal is for the participant to be able to see how many words there are in total in the sentence before clicking region by region, so I need spaces between the words rather than the regions. Like this:

---  ---  ---  ---  ---  
The dog  ---  ---  ---

Now, the participant can see how many words there are total with all the spaces between them but the regions are still the same.

What I tried so far:
I don’t know a ton about JS but I figured I would need to define word boundaries and region boundaries with separate delimiters (a comma for regions and an underscore for words). I basically only got that far though because, in the replaceWithdash function it needs to read region by region in order to display things correctly (I’m pretty sure). I have no idea how to also tell it to create spaces word by word. Maybe I need to make another variable for the word boundary delimiter? Something like
wordList = Sentence.split("_");
and then do something with that? Or is there another area about keypress display I can mess with?

Any help would be appreciated!!

You can split using spaces “_”

I was asked about SPR recently and created a demo

I was asked about the moving window but my plan for it would be to place the visible word in the calculated location – the problem with your method (which is programmatically far easier) is kerning. As the window moves the dashes to the right will move as well. However, it might still be a better option.

Thank you for the input! In another SPR experiment I did which was similar to the one you talk about in that post, I used spaces just like that, but that was because my regions were only 1 word each. The problem here is that i want to show spaces between words but display multiple-word regions. So, If I only split with dashes, I’ll only display word by word, hence me thinking I’ll have to use multiple delimiters.

Yes, I understand that you need two different delimiters in your case.

I don’t know if you could use a space and a non breaking space   I suspect that PsychoPy won’t render that correctly.

However, you could use space as one of your delimiters.

Dear @cousin63-lang,
I have a question regarding the other former experiment of yours in which the reasons 1 word each. I wonder if you have the code for that and how it worked for you. I don’t about you but I don’t care about dashes. The whole point of a moving window paradigm is, I believe, to make reading more similar to that of real life reading, from left to right. So, any ideas?

Btw, I’d be happy to help you with that issue, but I’m no good in coding.


Hey Zeinab,

To do the SPR moving window where its word by word display, use the same code I give, except in the “.split” function in Begin Routine, instead of a comma just put a space, like this:

sentenceList = Sentence.split(" ");
wordNumber = (- 2);

In your csv, just concatenate all words together to form the sentence in one column so that there are spaces between the words like normal text. Then tell Psychopy to read that one column and it should work!
Also, you might want to add this to the first routine you have in Begin Experiment:

shuffle = util.shuffle;
Array.prototype.append = [].push;
Array.prototype.index = [].indexOf;

I hope it all works out!

Thank you very much @cousin63-lang :herb:
I keep my fingers crossed for the success of your experiment :crossed_fingers:

And dear @wakecarter, could you try this code on that SPR once to see if it works? that would be great if it did, you know. :seedling:


Do you mean replacing letters with dashes?

Well, replacing them with dashes is the secondary goal, and i assume it’s not as important as that moving feature. This is a sample procedure in other theses:

Subjects pressed a button to reveal each word of the sentence, and they could see only one word at a time as the preceding word disappeared upon each button pressing. Most sentences appeared on a single line from left to right, but some of the long, experimental sentences did not fit on one line.

A trial was initiated by pressing the ‘Go’ key. Each trial sentence was preceded by a fixation star in the centre of the screen. When the subjects pressed the ‘Go’ key, the first segment appeared at the left edge in the vertical middle of the screen. At the next push of the key, the first segment disappeared and the second segment appeared to the right of the now-gone segment. All sentences fit on one line.

From a coding perspective it’s easier to replace the letters with a character than with nothing.

That’s alright. what I meant was the words displayed from left to right is the key to this form of presentation, that “moving feature”. If replacing them with dashes make it easier, well let them be; it’s a quite valid procedure in most papers too.
so do you think it’s possible to pull it off with this code? just testing. :seedling:

@jon, any ideas?

From what I can tell so far after a ton of trial and error with different methods, in order for the display to be region by region but for spaces to be shown between words in a region when they are covered with dashes, I need to manipulate the resulting dashed string, NOT how Java script is reading the initial string I give it. I’m currently trying to do this with a for loop that takes in the now dashed string result and tells it to make any character in “word” that is an underscore into a space in the result. Hopefully this will make it so that I’m basically telling java script to only care about regions but then putting a “space”-bandaid on top of the resulting dashed string.
I’m still working on this, but if anyone has insight on how to do this (I’m trying to use the replace function), please let me know!!!

The one thing I discovered when using the replace function in my Interactive Fiction paradigm is that in Python replace function replaces all instances whereas in JS it only replaces one so I have to run it multiple times.

Personally, I would loop through the string and create a parallel string of the same length which has a space where the original has a space and a dash in all other cases.

I think that could work too, but I’m unsure how I would do it.

I’ve added a dash based moving window and a moving word to my demo



Is it possible to run the reading task locally?

It should be fine. Have you given it a go?

Thanks @Wakecarter

I copied the code of the moving window, but it did not work.

Hello there. I know it’s quite sudden but I have a question with your demo…

I want to make a self paced reading task just like yours -with dashes - so I forked you and used your demo task.

It works perfectly fine but one problem I have is that letters do not replace with dashes… :sob::sob:

I took a video of the problem and do you mind if you can look through it? :pray::pray:

Ps., I am gonna change the you demo sentences with shorter lengths later - the one that I made (e.g., The band is playing songs.). Btw, I love your demo task!