URL of experiment: painpred [PsychoPy]
Description of the problem:
- OS: Android
- browser: Google Chrome
In order to get typed response from participants, I added a textbox from Builder window. It went well locally. Then I compile it to js code and run it on Pavlovia. It also went well in iPad (both Safari and Chrome). But when I tried it on mobile phone, the keyboard start to pop up continuously each frame.
I paste some of the javascript code which related to this textbox object here.
var PID_box;
/*******/
PID_box = new visual.TextBox({
win: psychoJS.window,
name: 'PID_box',
text: '',
font: 'Open Sans',
pos: [0, 0], letterHeight: 0.05,
//size change based on multiple devices (I am sure this part works)
size: [0.5*longside,0.1*longside], units: undefined,
color: 'white', colorSpace: 'rgb',
fillColor: [0.0039, 0.0039, 0.0039], borderColor: [(- 1.0), 1.0, 1.0],
languageStyle: 'LTR',
bold: false, italic: false,
opacity: 1,
padding: undefined,
//alignment: 'center',
editable: true,
multiline: true,
anchor: 'center',
depth: -4.0
});
/*****/
function addPIDRoutineBegin(snapshot) {
return async function () {
TrialHandler.fromSnapshot(snapshot); // ensure that .thisN vals are up to date
//--- Prepare to start Routine 'addPID' ---
t = 0;
addPIDClock.reset(); // clock
frameN = -1;
continueRoutine = true; // until we're told otherwise
// update component parameters for each repeat
PID_box.setText('');
PID_box.refresh();
PID_box.setText('');
// setup some python lists for storing info about the mouse_PID
// current position of the mouse:
mouse_PID.x = [];
mouse_PID.y = [];
mouse_PID.leftButton = [];
mouse_PID.midButton = [];
mouse_PID.rightButton = [];
mouse_PID.time = [];
mouse_PID.clicked_name = [];
gotValidClick = false; // until a click is received
// keep track of which components have finished
addPIDComponents = [];
addPIDComponents.push(PID_instruction);
addPIDComponents.push(PID_box);
addPIDComponents.push(next_button_PID);
addPIDComponents.push(mouse_PID);
for (const thisComponent of addPIDComponents)
if ('status' in thisComponent)
thisComponent.status = PsychoJS.Status.NOT_STARTED;
return Scheduler.Event.NEXT;
}
}
var prevButtonState;
var _mouseButtons;
var _mouseXYs;
function addPIDRoutineEachFrame() {
return async function () {
//--- Loop for each frame of Routine 'addPID' ---
// get current time
t = addPIDClock.getTime();
frameN = frameN + 1;// number of completed frames (so 0 is the first frame)
// update/draw components on each frame
// *PID_instruction* updates
if (t >= 0 && PID_instruction.status === PsychoJS.Status.NOT_STARTED) {
// keep track of start time/frame for later
PID_instruction.tStart = t; // (not accounting for frame time here)
PID_instruction.frameNStart = frameN; // exact frame index
PID_instruction.setAutoDraw(true);
}
// *PID_box* updates
if (t >= 0.0 && PID_box.status === PsychoJS.Status.NOT_STARTED) {
// keep track of start time/frame for later
PID_box.tStart = t; // (not accounting for frame time here)
PID_box.frameNStart = frameN; // exact frame index
PID_box.setAutoDraw(true);
}
// *next_button_PID* updates
if (t >= 0.0 && next_button_PID.status === PsychoJS.Status.NOT_STARTED) {
// keep track of start time/frame for later
next_button_PID.tStart = t; // (not accounting for frame time here)
next_button_PID.frameNStart = frameN; // exact frame index
next_button_PID.setAutoDraw(true);
}
// *mouse_PID* updates
if (t >= 0 && mouse_PID.status === PsychoJS.Status.NOT_STARTED) {
// keep track of start time/frame for later
mouse_PID.tStart = t; // (not accounting for frame time here)
mouse_PID.frameNStart = frameN; // exact frame index
mouse_PID.status = PsychoJS.Status.STARTED;
mouse_PID.mouseClock.reset();
prevButtonState = mouse_PID.getPressed(); // if button is down already this ISN'T a new click
}
if (mouse_PID.status === PsychoJS.Status.STARTED) { // only update if started and not finished!
_mouseButtons = mouse_PID.getPressed();
if (!_mouseButtons.every( (e,i,) => (e == prevButtonState[i]) )) { // button state changed?
prevButtonState = _mouseButtons;
if (_mouseButtons.reduce( (e, acc) => (e+acc) ) > 0) { // state changed to a new click
// check if the mouse was inside our 'clickable' objects
gotValidClick = false;
for (const obj of [next_button_PID]) {
if (obj.contains(mouse_PID)) {
gotValidClick = true;
mouse_PID.clicked_name.push(obj.name)
}
}
_mouseXYs = mouse_PID.getPos();
mouse_PID.x.push(_mouseXYs[0]);
mouse_PID.y.push(_mouseXYs[1]);
mouse_PID.leftButton.push(_mouseButtons[0]);
mouse_PID.midButton.push(_mouseButtons[1]);
mouse_PID.rightButton.push(_mouseButtons[2]);
mouse_PID.time.push(mouse_PID.mouseClock.getTime());
if (gotValidClick === true) { // abort routine on response
continueRoutine = false;
}
}
}
}
// check for quit (typically the Esc key)
if (psychoJS.experiment.experimentEnded || psychoJS.eventManager.getKeys({keyList:['escape']}).length > 0) {
return quitPsychoJS('The [Escape] key was pressed. Goodbye!', false);
}
// check if the Routine should terminate
if (!continueRoutine) { // a component has requested a forced-end of Routine
return Scheduler.Event.NEXT;
}
continueRoutine = false; // reverts to True if at least one component still running
for (const thisComponent of addPIDComponents)
if ('status' in thisComponent && thisComponent.status !== PsychoJS.Status.FINISHED) {
continueRoutine = true;
break;
}
// refresh the screen if continuing
if (continueRoutine) {
return Scheduler.Event.FLIP_REPEAT;
} else {
return Scheduler.Event.NEXT;
}
};
}
function addPIDRoutineEnd(snapshot) {
return async function () {
//--- Ending Routine 'addPID' ---
for (const thisComponent of addPIDComponents) {
if (typeof thisComponent.setAutoDraw === 'function') {
thisComponent.setAutoDraw(false);
}
}
psychoJS.experiment.addData('PID_box.text',PID_box.text)
// store data for psychoJS.experiment (ExperimentHandler)
if (mouse_PID.x) { psychoJS.experiment.addData('mouse_PID.x', mouse_PID.x[0])};
if (mouse_PID.y) { psychoJS.experiment.addData('mouse_PID.y', mouse_PID.y[0])};
if (mouse_PID.leftButton) { psychoJS.experiment.addData('mouse_PID.leftButton', mouse_PID.leftButton[0])};
if (mouse_PID.midButton) { psychoJS.experiment.addData('mouse_PID.midButton', mouse_PID.midButton[0])};
if (mouse_PID.rightButton) { psychoJS.experiment.addData('mouse_PID.rightButton', mouse_PID.rightButton[0])};
if (mouse_PID.time) { psychoJS.experiment.addData('mouse_PID.time', mouse_PID.time[0])};
if (mouse_PID.clicked_name) { psychoJS.experiment.addData('mouse_PID.clicked_name', mouse_PID.clicked_name[0])};
// the Routine "addPID" was not non-slip safe, so reset the non-slip timer
routineTimer.reset();
// Routines running outside a loop should always advance the datafile row
if (currentLoop === psychoJS.experiment) {
psychoJS.experiment.nextEntry(snapshot);
}
return Scheduler.Event.NEXT;
}
}