mirror of
https://github.com/jspsych/jsPsych.git
synced 2025-05-10 11:10:54 +00:00
Simplify canvas-button-response plugin DOM structure and make button_html
a function parameter
This commit is contained in:
parent
bcf2642b89
commit
5970531585
@ -3,7 +3,7 @@
|
||||
<head>
|
||||
<script src="../packages/jspsych/dist/index.browser.js"></script>
|
||||
<script src="../packages/plugin-canvas-button-response/dist/index.browser.js"></script>
|
||||
<link rel="stylesheet" href="../packages/jspsych/css/jspsych.css">
|
||||
<link rel="stylesheet" href="../packages/jspsych/css/jspsych.css" />
|
||||
</head>
|
||||
<body></body>
|
||||
<script>
|
||||
@ -78,7 +78,7 @@
|
||||
timeline: [{
|
||||
type: jsPsychCanvasButtonResponse,
|
||||
stimulus: function (c) {
|
||||
filledCirc(c, jsPsych.timelineVariable('radius'), jsPsych.timelineVariable('color'));
|
||||
filledCirc(c, jsPsych.evaluateTimelineVariable('radius'), jsPsych.evaluateTimelineVariable('color'));
|
||||
},
|
||||
choices: ['Red', 'Green', 'Blue'],
|
||||
prompt: '<p>What color is the circle?</p>',
|
||||
@ -92,6 +92,5 @@
|
||||
};
|
||||
|
||||
jsPsych.run([circle_1, circle_2, lines, circle_procedure]);
|
||||
|
||||
</script>
|
||||
</html>
|
||||
</html>
|
||||
|
@ -16,12 +16,16 @@ const info = <const>{
|
||||
default: undefined,
|
||||
array: true,
|
||||
},
|
||||
/** The html of the button. Can create own style. */
|
||||
/**
|
||||
* A function that, given a choice and its index, returns the HTML string of that choice's
|
||||
* button.
|
||||
*/
|
||||
button_html: {
|
||||
type: ParameterType.HTML_STRING,
|
||||
type: ParameterType.FUNCTION,
|
||||
pretty_name: "Button HTML",
|
||||
default: '<button class="jspsych-btn">%choice%</button>',
|
||||
array: true,
|
||||
default: function (choice: string, choice_index: number) {
|
||||
return `<button class="jspsych-btn">${choice}</button>`;
|
||||
},
|
||||
},
|
||||
/** Any content here will be displayed under the button. */
|
||||
prompt: {
|
||||
@ -85,73 +89,50 @@ class CanvasButtonResponsePlugin implements JsPsychPlugin<Info> {
|
||||
constructor(private jsPsych: JsPsych) {}
|
||||
|
||||
trial(display_element: HTMLElement, trial: TrialType<Info>) {
|
||||
// create canvas
|
||||
var html =
|
||||
'<div id="jspsych-canvas-button-response-stimulus">' +
|
||||
'<canvas id="jspsych-canvas-stimulus" height="' +
|
||||
trial.canvas_size[0] +
|
||||
'" width="' +
|
||||
trial.canvas_size[1] +
|
||||
'"></canvas>' +
|
||||
"</div>";
|
||||
// Create canvas
|
||||
const stimulusElement = document.createElement("div");
|
||||
stimulusElement.id = "jspsych-canvas-button-response-stimulus";
|
||||
|
||||
//display buttons
|
||||
var buttons = [];
|
||||
if (Array.isArray(trial.button_html)) {
|
||||
if (trial.button_html.length == trial.choices.length) {
|
||||
buttons = trial.button_html;
|
||||
} else {
|
||||
console.error(
|
||||
"Error in canvas-button-response plugin. The length of the button_html array does not equal the length of the choices array"
|
||||
);
|
||||
}
|
||||
} else {
|
||||
for (var i = 0; i < trial.choices.length; i++) {
|
||||
buttons.push(trial.button_html);
|
||||
}
|
||||
}
|
||||
html += '<div id="jspsych-canvas-button-response-btngroup">';
|
||||
for (var i = 0; i < trial.choices.length; i++) {
|
||||
var str = buttons[i].replace(/%choice%/g, trial.choices[i]);
|
||||
html +=
|
||||
'<div class="jspsych-canvas-button-response-button" style="display: inline-block; margin:' +
|
||||
trial.margin_vertical +
|
||||
" " +
|
||||
trial.margin_horizontal +
|
||||
'" id="jspsych-canvas-button-response-button-' +
|
||||
i +
|
||||
'" data-choice="' +
|
||||
i +
|
||||
'">' +
|
||||
str +
|
||||
"</div>";
|
||||
}
|
||||
html += "</div>";
|
||||
const canvasElement = document.createElement("canvas");
|
||||
canvasElement.id = "jspsych-canvas-stimulus";
|
||||
canvasElement.height = trial.canvas_size[0];
|
||||
canvasElement.width = trial.canvas_size[1];
|
||||
stimulusElement.appendChild(canvasElement);
|
||||
|
||||
//show prompt if there is one
|
||||
display_element.appendChild(stimulusElement);
|
||||
|
||||
// Display buttons
|
||||
const buttonGroupElement = document.createElement("div");
|
||||
buttonGroupElement.id = "jspsych-canvas-button-response-btngroup";
|
||||
buttonGroupElement.style.cssText = `
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
gap: ${trial.margin_vertical} ${trial.margin_horizontal};
|
||||
padding: ${trial.margin_vertical} ${trial.margin_horizontal};
|
||||
`;
|
||||
|
||||
for (const [choiceIndex, choice] of trial.choices.entries()) {
|
||||
buttonGroupElement.insertAdjacentHTML("beforeend", trial.button_html(choice, choiceIndex));
|
||||
const buttonElement = buttonGroupElement.lastChild as HTMLElement;
|
||||
buttonElement.dataset.choice = choiceIndex.toString();
|
||||
buttonElement.addEventListener("click", () => {
|
||||
after_response(choiceIndex);
|
||||
});
|
||||
}
|
||||
|
||||
display_element.appendChild(buttonGroupElement);
|
||||
|
||||
// Show prompt if there is one
|
||||
if (trial.prompt !== null) {
|
||||
html += trial.prompt;
|
||||
display_element.insertAdjacentHTML("beforeend", trial.prompt);
|
||||
}
|
||||
display_element.innerHTML = html;
|
||||
|
||||
//draw
|
||||
let c = document.getElementById("jspsych-canvas-stimulus");
|
||||
trial.stimulus(c);
|
||||
trial.stimulus(canvasElement);
|
||||
|
||||
// start time
|
||||
var start_time = performance.now();
|
||||
|
||||
// add event listeners to buttons
|
||||
for (var i = 0; i < trial.choices.length; i++) {
|
||||
display_element
|
||||
.querySelector<HTMLButtonElement>("#jspsych-canvas-button-response-button-" + i)
|
||||
.addEventListener("click", (e: MouseEvent) => {
|
||||
var btn_el = e.currentTarget as Element;
|
||||
var choice = btn_el.getAttribute("data-choice"); // don't use dataset for jsdom compatibility
|
||||
after_response(choice);
|
||||
});
|
||||
}
|
||||
|
||||
// store response
|
||||
var response = {
|
||||
rt: null,
|
||||
@ -186,14 +167,11 @@ class CanvasButtonResponsePlugin implements JsPsychPlugin<Info> {
|
||||
|
||||
// after a valid response, the stimulus will have the CSS class 'responded'
|
||||
// which can be used to provide visual feedback that a response was recorded
|
||||
display_element.querySelector("#jspsych-canvas-button-response-stimulus").className +=
|
||||
" responded";
|
||||
stimulusElement.classList.add("responded");
|
||||
|
||||
// disable all the buttons after a response
|
||||
var btns = document.querySelectorAll(".jspsych-canvas-button-response-button button");
|
||||
for (var i = 0; i < btns.length; i++) {
|
||||
//btns[i].removeEventListener('click');
|
||||
btns[i].setAttribute("disabled", "disabled");
|
||||
for (const button of buttonGroupElement.children) {
|
||||
button.setAttribute("disabled", "disabled");
|
||||
}
|
||||
|
||||
if (trial.response_ends_trial) {
|
||||
@ -204,9 +182,7 @@ class CanvasButtonResponsePlugin implements JsPsychPlugin<Info> {
|
||||
// hide image if timing is set
|
||||
if (trial.stimulus_duration !== null) {
|
||||
this.jsPsych.pluginAPI.setTimeout(() => {
|
||||
display_element.querySelector<HTMLElement>(
|
||||
"#jspsych-canvas-button-response-stimulus"
|
||||
).style.visibility = "hidden";
|
||||
stimulusElement.style.visibility = "hidden";
|
||||
}, trial.stimulus_duration);
|
||||
}
|
||||
|
||||
@ -262,7 +238,9 @@ class CanvasButtonResponsePlugin implements JsPsychPlugin<Info> {
|
||||
|
||||
if (data.rt !== null) {
|
||||
this.jsPsych.pluginAPI.clickTarget(
|
||||
display_element.querySelector(`div[data-choice="${data.response}"] button`),
|
||||
display_element.querySelector(
|
||||
`#jspsych-canvas-button-response-btngroup [data-choice="${data.response}"]`
|
||||
),
|
||||
data.rt
|
||||
);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user