diff --git a/examples/jspsych-virtual-chinrest.html b/examples/jspsych-virtual-chinrest.html
index 46fe05df..3598b969 100644
--- a/examples/jspsych-virtual-chinrest.html
+++ b/examples/jspsych-virtual-chinrest.html
@@ -4,11 +4,7 @@
-
-
-
-
+
diff --git a/plugins/jspsych-virtual-chinrest.js b/plugins/jspsych-virtual-chinrest.js
index 3b0159ce..7ba7cf00 100644
--- a/plugins/jspsych-virtual-chinrest.js
+++ b/plugins/jspsych-virtual-chinrest.js
@@ -97,7 +97,7 @@ jsPsych.plugins["virtual-chinrest"] = (function () {
default: "Start",
description: "Content of the start button for the blindspot tasks.",
},
-
+
blindspot_measurements_prompt: {
type: jsPsych.plugins.parameterType.STRING,
default: "Remaining measurements: ",
@@ -105,11 +105,11 @@ jsPsych.plugins["virtual-chinrest"] = (function () {
},
viewing_distance_report: {
type: jsPsych.plugins.parameterType.STRING,
- default: "
Based on your responses, you are sitting about from the screen
Does that seem about right?
",
+ default: "Based on your responses, you are sitting about from the screen.
Does that seem about right?
",
description:
'If "none" is given, viewing distance will not be reported to the participant',
},
- redo_measurement_button_label: {
+ redo_measurement_button_label: {
type: jsPsych.plugins.parameterType.STRING,
default: 'No, that is not close. Try again.'
},
@@ -127,25 +127,19 @@ jsPsych.plugins["virtual-chinrest"] = (function () {
console.error("Blindspot repetitions set to 0, so resizing to degrees of visual angle is not possible!");
}
- /* some additional parameter configuration */
- var w = window.innerWidth;
- var h = window.innerHeight;
-
- const screen_size_px = [w, "x", h];
-
+ /* some additional parameter configuration */
let trial_data = {
item_width_mm: trial.item_width_mm,
item_height_mm: trial.item_height_mm, //card dimension: 85.60 × 53.98 mm (3.370 × 2.125 in)
};
- let config_data = {
+ let blindspot_config_data = {
ball_pos: [],
slider_clck: false,
};
- let aspect_ratio = 1;
+ let aspect_ratio = trial.item_width_mm / trial.item_height_mm;
- aspect_ratio = trial.item_width_mm / trial.item_height_mm;
const start_div_height =
aspect_ratio < 1
? trial.item_init_size
@@ -160,7 +154,7 @@ jsPsych.plugins["virtual-chinrest"] = (function () {
let pagesize_content = `
-
${trial.adjustment_prompt}
@@ -186,7 +180,7 @@ jsPsych.plugins["virtual-chinrest"] = (function () {
${trial.viewing_distance_report}
` : ''
- }
+ }
`
/* create content for final report screen */
@@ -200,73 +194,84 @@ jsPsych.plugins["virtual-chinrest"] = (function () {
`
-
- /* show first screen */
- display_element.innerHTML = `
-
- ${pagesize_content}
-
- `
+ display_element.innerHTML = ``
const start_time = performance.now();
+ startResizePhase();
- // Event listeners for mouse-based resize
- let dragging = false;
- let origin_x, origin_y;
- let cx, cy;
- const scale_div = display_element.querySelector("#item");
+ function startResizePhase() {
+ display_element.querySelector('#content').innerHTML = pagesize_content;
- function mouseupevent() {
- dragging = false;
- };
- document.addEventListener("mouseup", mouseupevent);
+ // Event listeners for mouse-based resize
+ let dragging = false;
+ let origin_x, origin_y;
+ let cx, cy;
+ const scale_div = display_element.querySelector("#item");
- function mousedownevent(e) {
- e.preventDefault();
- dragging = true;
- origin_x = e.pageX;
- origin_y = e.pageY;
- cx = parseInt(scale_div.style.width);
- cy = parseInt(scale_div.style.height);
- };
- display_element.querySelector("#jspsych-resize-handle").addEventListener("mousedown", mousedownevent);
+ function mouseupevent() {
+ dragging = false;
+ };
+ document.addEventListener("mouseup", mouseupevent);
- function resizeevent(e) {
- if (dragging) {
- let dx = e.pageX - origin_x;
- let dy = e.pageY - origin_y;
+ function mousedownevent(e) {
+ e.preventDefault();
+ dragging = true;
+ origin_x = e.pageX;
+ origin_y = e.pageY;
+ cx = parseInt(scale_div.style.width);
+ cy = parseInt(scale_div.style.height);
+ };
+ display_element.querySelector("#jspsych-resize-handle").addEventListener("mousedown", mousedownevent);
- if (Math.abs(dx) >= Math.abs(dy)) {
- scale_div.style.width =
- Math.round(Math.max(20, cx + dx * 2)) + "px";
- scale_div.style.height =
- Math.round(Math.max(20, cx + dx * 2) / aspect_ratio) + "px";
- } else {
- scale_div.style.height =
- Math.round(Math.max(20, cy + dy * 2)) + "px";
- scale_div.style.width =
- Math.round(aspect_ratio * Math.max(20, cy + dy * 2)) + "px";
+ function resizeevent(e) {
+ if (dragging) {
+ let dx = e.pageX - origin_x;
+ let dy = e.pageY - origin_y;
+
+ if (Math.abs(dx) >= Math.abs(dy)) {
+ scale_div.style.width =
+ Math.round(Math.max(20, cx + dx * 2)) + "px";
+ scale_div.style.height =
+ Math.round(Math.max(20, cx + dx * 2) / aspect_ratio) + "px";
+ } else {
+ scale_div.style.height =
+ Math.round(Math.max(20, cy + dy * 2)) + "px";
+ scale_div.style.width =
+ Math.round(aspect_ratio * Math.max(20, cy + dy * 2)) + "px";
+ }
}
}
+ display_element.addEventListener("mousemove", resizeevent);
+
+ display_element.querySelector("#end_resize_phase").addEventListener("click", finishResizePhase);
+
}
- display_element.addEventListener("mousemove", resizeevent);
- display_element.querySelector("#end_resize_phase").addEventListener("click", finishResizePhase);
-
- function finishResizePhase(){
+ function finishResizePhase() {
+ // add item width info to data
+ const item_width_px = getScaledItemWidth();
+ trial_data["item_width_px"] = Math.round(item_width_px);
+ const px2mm = convertPixelsToMM(item_width_px);
+ trial_data["px2mm"] = accurateRound(px2mm, 2);
// check what to do next
if (trial.blindspot_reps > 0) {
- get_item_width(); // modifies trial data
- configureBlindSpot();
+ startBlindSpotPhase();
} else {
- distanceSetup.px2mm(get_item_width());
endTrial();
}
}
- function configureBlindSpot() {
+ function startBlindSpotPhase() {
+ // reset the config data in case we are redoing the measurement
+ blindspot_config_data = {
+ ball_pos: [],
+ slider_clck: false,
+ };
+ // add the content to the page
document.querySelector("#content").innerHTML = blindspot_content;
+ // draw the ball and fixation square
drawBall();
+ // wait for a spacebar to begin the animations
jsPsych.pluginAPI.getKeyboardResponse({
callback_function: startBall,
valid_responses: ['space'],
@@ -276,8 +281,7 @@ jsPsych.plugins["virtual-chinrest"] = (function () {
})
}
- var ball_position_listener = null;
- function startBall(){
+ function startBall() {
ball_position_listener = jsPsych.pluginAPI.getKeyboardResponse({
callback_function: recordPosition,
valid_responses: ['space'],
@@ -288,7 +292,7 @@ jsPsych.plugins["virtual-chinrest"] = (function () {
animateBall();
}
- function finishBlindSpotPhase(){
+ function finishBlindSpotPhase() {
ball.stop();
jsPsych.pluginAPI.cancelAllKeyboardResponses();
@@ -296,20 +300,18 @@ jsPsych.plugins["virtual-chinrest"] = (function () {
showReport();
}
- function showReport(){
+ function showReport() {
// Display data
display_element.querySelector("#content").innerHTML = report_content;
- display_element.querySelector('#distance-estimate').innerHTML = `${Math.round(trial_data["view_dist_mm"] / 10)} cm`
+ display_element.querySelector('#distance-estimate').innerHTML = `
+ ${Math.round(trial_data["view_dist_mm"] / 10)} cm (${Math.round(trial_data["view_dist_mm"]*0.0393701)} inches)
+ `
- display_element.querySelector("#redo_blindspot").addEventListener('click', configureBlindSpot)
+ display_element.querySelector("#redo_blindspot").addEventListener('click', startBlindSpotPhase)
display_element.querySelector("#proceed").addEventListener('click', endTrial);
}
- function endTrial() {
- // finish trial
- trial_data.rt = performance.now() - start_time;
- display_element.innerHTML = "";
-
+ function computeTransformation() {
trial_data.item_width_deg =
(2 *
Math.atan(
@@ -357,43 +359,49 @@ jsPsych.plugins["virtual-chinrest"] = (function () {
delete trial_data.px2deg;
delete trial_data.item_width_deg;
}
- // NEED TO REMOVE EVENT LISTENERS
-
- jsPsych.finishTrial(trial_data);
- jsPsych.pluginAPI.cancelAllKeyboardResponses();
}
- function get_item_width() {
- const item_width_px = parseFloat(
- getComputedStyle(document.querySelector("#item"), null).width.replace(
- "px",
- ""
- )
- );
-
- trial_data["item_width_px"] = distanceSetup.round(item_width_px, 2);
- return item_width_px;
+ function endTrial() {
+
+ // finish trial
+ trial_data.rt = performance.now() - start_time;
+
+ // remove lingering event listeners, just in case
+ jsPsych.pluginAPI.cancelAllKeyboardResponses();
+
+ // compute final data
+ computeTransformation();
+
+ // clear the display
+ display_element.innerHTML = "";
+
+ // finish the trial
+ jsPsych.finishTrial(trial_data);
+
+ }
+
+ function getScaledItemWidth() {
+ return document.querySelector('#item').getBoundingClientRect().width;
}
function drawBall(pos = 180) {
// pos: define where the fixation square should be.
var mySVG = SVG("svgDiv");
- const item_width_px = trial_data["item_width_px"];
- const rectX = distanceSetup.px2mm(item_width_px) * pos;
+ const rectX = trial_data["px2mm"] * pos;
const ballX = rectX * 0.6; // define where the ball is
var ball = mySVG.circle(30).move(ballX, 50).fill("#f00");
window.ball = ball;
var square = mySVG.rect(30, 30).move(Math.min(rectX - 50, 950), 50); //square position
- config_data["square_pos"] = distanceSetup.round(square.cx(), 2);
- config_data["rectX"] = rectX;
- config_data["ballX"] = ballX;
+ blindspot_config_data["square_pos"] = accurateRound(square.cx(), 2);
+ blindspot_config_data["rectX"] = rectX;
+ blindspot_config_data["ballX"] = ballX;
}
function animateBall() {
ball
.animate(7000)
.during(function (pos) {
- moveX = -pos * config_data["ballX"];
+ moveX = -pos * blindspot_config_data["ballX"];
window.moveX = moveX;
moveY = 0;
ball.attr({ transform: "translate(" + moveX + "," + moveY + ")" }); //jqueryToVanilla: el.getAttribute('');
@@ -401,22 +409,22 @@ jsPsych.plugins["virtual-chinrest"] = (function () {
.loop(true, false)
.after(function () {
animateBall();
- });
+ });
}
-
- function recordPosition(info) {
+
+ function recordPosition() {
// angle: define horizontal blind spot entry point position in degrees.
const angle = 13.5;
-
- config_data["ball_pos"].push(distanceSetup.round(ball.cx() + moveX, 2));
- var sum = config_data["ball_pos"].reduce((a, b) => a + b, 0);
- var ballPosLen = config_data["ball_pos"].length;
- config_data["avg_ball_pos"] = distanceSetup.round(sum / ballPosLen, 2);
+
+ blindspot_config_data["ball_pos"].push(accurateRound(ball.cx() + moveX, 2));
+ var sum = blindspot_config_data["ball_pos"].reduce((a, b) => a + b, 0);
+ var ballPosLen = blindspot_config_data["ball_pos"].length;
+ blindspot_config_data["avg_ball_pos"] = accurateRound(sum / ballPosLen, 2);
var ball_sqr_distance =
- (config_data["square_pos"] - config_data["avg_ball_pos"]) /
+ (blindspot_config_data["square_pos"] - blindspot_config_data["avg_ball_pos"]) /
trial_data["px2mm"];
var viewDistance = ball_sqr_distance / Math.radians(angle);
- trial_data["view_dist_mm"] = distanceSetup.round(viewDistance, 2);
+ trial_data["view_dist_mm"] = accurateRound(viewDistance, 2);
//counter and stop
var counter = Number(document.querySelector("#click").textContent);
@@ -429,20 +437,17 @@ jsPsych.plugins["virtual-chinrest"] = (function () {
ball.stop();
animateBall();
}
-
+
}
- var distanceSetup = {
- round: function (value, decimals) {
- return Number(Math.round(value + "e" + decimals) + "e-" + decimals);
- },
- px2mm: function (item_width_px) {
- const px2mm = item_width_px / trial_data["item_width_mm"];
- trial_data["px2mm"] = distanceSetup.round(px2mm, 2);
- return px2mm;
- }
+ function convertPixelsToMM(item_width_px){
+ const px2mm = item_width_px / trial_data["item_width_mm"];
+ return px2mm;
}
+ function accurateRound(value, decimals){
+ return Number(Math.round(value+'e'+decimals)+'e-'+decimals);
+ }
};