PennController for IBEX › Forums › Support › Refreshing canvas
- This topic has 10 replies, 2 voices, and was last updated 3 years, 9 months ago by
rventura.
-
AuthorPosts
-
May 24, 2021 at 10:19 am #6982
rventura
ParticipantHi Jeremy,
I’m running into the following issue: (1) I want to print two canvases to a trial, (2) I want a button on the second canvas to continue to the next trial screen, (3) I want a timer to refresh the first canvas with some changes, and (4) I want the changes made to the first canvas to stay in place after users click on the button to continue to the next trial screen. I am able to do items 1 to 3, but not 4: whenever users click on the button to continue to the next trial screen, the changes made to the first canvas disappear. My question is thus how can I ensure that changes remain in place after users click on the button to continue to the next trial screen?
Here’s my code:
Template( GetTable("cond_test.csv"), row => newTrial("Phase_3a", newTimer("wait_1", 10000) .start(), newTimer("wait_2", 2000) .start(), //Initial canvas newCanvas("start", 800,50) .add( 0, 0, newText("player 1", "PLAYER 1 - OTHER") ) .add( 600, 0, newText("player 2", "PLAYER 2 - YOU") ) .print() , //Final canvas newCanvas("time up", 800,50) .add( 0, 0, newText("player 1", "PLAYER 1 - OTHER") ) .add( 600, 0, newText("player 2", "PLAYER 2 - YOU") ) .add( 600, 50, newText("player 2", "<i>Your time is up. Get ready for next phase!</i>") ), //Canvas for players newCanvas("players", 800,400) .add( 600, 20, newImage("timer 1", "twomin.gif") ) .add( 500, 50, newImage("pic_learn", row.File ) ) .add( 645, 350, newText( row.Noun ) ) .add( 0, 0, getTimer("wait_1") .callback( getCanvas("start").remove() ) .callback( getCanvas("players").remove() ) .callback( getCanvas("time up").print() ) ) .add( 645, 400, newButton("next", "Next") .print() ) .print() , getTimer("wait_2") .callback( getCanvas("start").add( 0,20, newText("<i>Player 1 is ready!</i>") ).refresh() ), getButton("next") .wait() ).log("Cond", row.Cond).log("Chain", row.Group).log("Gen", row.Gen).log("Freq", row.Freq ).log("Noun", row.Noun ).log("File", row.File ).log("ID", GetURLParameter( "ID" ) ) );
Thank you so much in advance for any advice you might have!
Best,
RafaelMay 24, 2021 at 10:58 am #6985Jeremy
KeymasterHi Rafael,
The last command in your trial is
wait
on the Button element, so whenever the button is clicked, the trial ends, and all elements are removed from the page, so you’ll just no longer be able to see any changes to the Canvas elements after the click. You will either need to keep track of things across trials using a global Var element and testing it at the beginning of the trial to run differentadd
orprint
commands accordingly, or change your approach of your task and incorporate it within a single trialA couple tips: if you’re not
get
ting the Text elements, you don’t need to explicitly give them names (right now you’re creating two distinct elements both named “player 1” and three distinct elements all named “player 2”). Timer elements have no visual content, no it doesn’t make much sense toadd
them to a Canvas element. You could simply attach yourcallback
commands directly onto thenewTimer
command (also, you can pass three comma-separated commands tocallback
, no need to call threecallback
s in a row)Jeremy
May 25, 2021 at 7:39 pm #6992rventura
ParticipantHi Jeremy,
Thank you, that’s very helpful! A further question I have is: how can I time all the trials in the template? If a timer starts in the beginning of a trial, then a new timer starts every time the user clicks on the button and the user is taken to the next trial. Is there a general way to ensure that users are given a limited amount of time to finish all the trials in the template?
Many thanks!
Best,
RafaelMay 26, 2021 at 9:24 am #6997Jeremy
KeymasterHi Rafael,
The reasoning is the same here: elements are parts of trials, so when their trial ends, they cease to exist. The only exception is the Var element, which can be made
global
so you can access and manipulate its value across trialsIf you need to keep track of how much time has passed since the beginning of the experiment, you can set a javascript variable to
Date.now()
and check it on every trial, for example inside aHeader
. Here’s an example that will print a 2min timer in the top-left corner of the page, and clear the screen and print a “Timed out!” message when there’s not time left:ALLOTEDTIME = 2*60*1000 startTime = Date.now() toMinSec = v=>Math.floor((ALLOTEDTIME-v)/60000)+":"+Math.floor(((ALLOTEDTIME-v)/1000)%60) Header( newText("timer", "").print("left at 2em", "top at 2em") , newVar("time elapsed") .set(v=>Date.now()-startTime) .test.is(v=>v>ALLOTEDTIME).success( end() ) , newTimer("timeout", 500) .callback( getVar("time elapsed") .set(v=>Date.now()-startTime) .test.is(v=>v>ALLOTEDTIME) .success( clear() , newText("Time out!").print() , newButton().wait() ) .failure( getVar("time elapsed").set(toMinSec) , getText("timer").text(getVar("time elapsed")) , getTimer("timeout").start() ) ) .start() )
Jeremy
June 7, 2021 at 8:42 am #7022rventura
ParticipantHi Jeremy,
That’s perfect, thank you! I have yet another question. I want to have a score tracker and for that I initialize a global variable with newVar(“value”, 0).global(). But when I try to update a Text element with getText(“value”).text( getVar(“value”) ), I get an error message I cannot decipher. The code and the error message are below:
newTrial("Begin_2", newVar("value", 0).global(), newText("<h4>You are about to start Phase 2!</h4>").print(), newButton("Begin Phase 2!") .center() .print() .wait() ); Template( GetTable( "icon.csv" ), row => newTrial("Phase_2", newCanvas("score", 600,20) .add( 275, 0, newText("score", "score: ") ).print() .add( 325, 0, newText( "value", "0" ) ).print() , getText("value").text( getVar("value") ), );
And the error message:
[8:33:40] Command ‘0’ unknown on Var element ‘value’. (PennController: 34) [8:33:40] Command ‘length’ unknown on Var element ‘value’. (PennController: 34) [8:33:40] Command ‘parentNode’ unknown on Var element ‘value’. (PennController: 34)
Thanks,
RafaelJune 7, 2021 at 11:54 am #7027Jeremy
KeymasterHi Rafael,
The
Template
command from your post contains a trailing,
aftergetText("value").text( getVar("value") )
and misses a closing parenthesis (you seem to include a closing parenthesis forTemplate(
but no closing parenthesis fornewTrial(
)Once I fix these two points, your scripts runs smoothly for me. I’m using PennController 2.0.alpha. If you are using an older version, it could be that using the same name (
"value"
) both for the Text element and for the Var element creates a conflict, so maybe try using a different name for your Text element (eg."value display"
)Jeremy
June 7, 2021 at 12:16 pm #7030rventura
ParticipantHi Jeremy,
Thanks for the quick reply! The code that I posted here had a few typos, but the code that’s giving the error message didn’t. My bad for obscuring the issue in a failed attempt to make the post easier to read. Besides, missing parentheses and extra comes don’t usually give me the error messages I’m receiving. Is there a way to check/update my PennController version? I gave the elements different names but still get the same error.
Here’s the full code:
newTrial("Begin_2", // newVar("value", 0).global(), newText("<h4>You are about to start Phase 2!</h4>") .print(), newText("<p> </p>").print(), newButton("Begin Phase 2!") .center() .print() .wait() ); //Phase 2: Produce Template( GetTable( "icon.csv" ), row => newTrial("Phase_2", // newCanvas("score", 600,20) .add( 275, 0, newText("score", "score: ") ).print() .add( 325, 0, newText( "score_value", "0" ) ).print() , getText("score_value").text( getVar("value") ), // newCanvas("next_trial", 600,250) .add( "center at 50%", "middle at 50%", newText("<p>Next . . .</p>") ).print() , newTimer("wait", 600).start().wait(), getCanvas("next_trial").remove(), newCanvas(600,250) .add("center at 50%", "middle at 50%", newImage("pic", row.File)) .print() , newScale("answer", row.A1, row.A2, row.A3, row.A4 ) .center() .vertical() .labelsPosition("right") .print() .wait() , getScale("answer") .test.selected( row.Noun1) .or( getScale("answer").test.selected( row.Noun2) ) .success( getVar("value").set( v => v+1 ), getText("score_value").text( getVar("value") ) ) .failure( getText("score_value").text( getVar("value") ) ) , newText("<p> </p>").print(), newButton("next", "Next") .center() .print() .wait() ) );
Best,
RafaelJune 7, 2021 at 2:31 pm #7033Jeremy
KeymasterThe Debug popup’s title shows the project’s PennController version. Feel free to share the demonstration link to your project here or at support@pcibex.net, which will make it easier to view the project’s code (and avoid any typo-insertion issues) and also the version of PennController it uses
Jeremy
June 7, 2021 at 2:49 pm #7034rventura
ParticipantGreat, thank you! It looks like I’m using v2.0.alpha. Here’s the demo link:
https://farm.pcibex.net/r/ZStOSj/experiment.html?test=true
Best,
RafaelJune 7, 2021 at 3:01 pm #7036Jeremy
KeymasterI’ve been working and updating 2.0.alpha on the farm, I think your project uses a slightly older version than the one I was testing your code with
Download this file and replace your project’s Modules/PennController.js file with it: https://raw.githubusercontent.com/PennController/penncontroller/master/dist/PennController.js
Jeremy
June 7, 2021 at 3:06 pm #7037rventura
ParticipantIt’s working now, thank you!
-
AuthorPosts
- You must be logged in to reply to this topic.