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>
|
<head>
|
||||||
<script src="../packages/jspsych/dist/index.browser.js"></script>
|
<script src="../packages/jspsych/dist/index.browser.js"></script>
|
||||||
<script src="../packages/plugin-canvas-button-response/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>
|
</head>
|
||||||
<body></body>
|
<body></body>
|
||||||
<script>
|
<script>
|
||||||
@ -78,7 +78,7 @@
|
|||||||
timeline: [{
|
timeline: [{
|
||||||
type: jsPsychCanvasButtonResponse,
|
type: jsPsychCanvasButtonResponse,
|
||||||
stimulus: function (c) {
|
stimulus: function (c) {
|
||||||
filledCirc(c, jsPsych.timelineVariable('radius'), jsPsych.timelineVariable('color'));
|
filledCirc(c, jsPsych.evaluateTimelineVariable('radius'), jsPsych.evaluateTimelineVariable('color'));
|
||||||
},
|
},
|
||||||
choices: ['Red', 'Green', 'Blue'],
|
choices: ['Red', 'Green', 'Blue'],
|
||||||
prompt: '<p>What color is the circle?</p>',
|
prompt: '<p>What color is the circle?</p>',
|
||||||
@ -92,6 +92,5 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
jsPsych.run([circle_1, circle_2, lines, circle_procedure]);
|
jsPsych.run([circle_1, circle_2, lines, circle_procedure]);
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
</html>
|
</html>
|
||||||
|
@ -16,12 +16,16 @@ const info = <const>{
|
|||||||
default: undefined,
|
default: undefined,
|
||||||
array: true,
|
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: {
|
button_html: {
|
||||||
type: ParameterType.HTML_STRING,
|
type: ParameterType.FUNCTION,
|
||||||
pretty_name: "Button HTML",
|
pretty_name: "Button HTML",
|
||||||
default: '<button class="jspsych-btn">%choice%</button>',
|
default: function (choice: string, choice_index: number) {
|
||||||
array: true,
|
return `<button class="jspsych-btn">${choice}</button>`;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
/** Any content here will be displayed under the button. */
|
/** Any content here will be displayed under the button. */
|
||||||
prompt: {
|
prompt: {
|
||||||
@ -85,73 +89,50 @@ class CanvasButtonResponsePlugin implements JsPsychPlugin<Info> {
|
|||||||
constructor(private jsPsych: JsPsych) {}
|
constructor(private jsPsych: JsPsych) {}
|
||||||
|
|
||||||
trial(display_element: HTMLElement, trial: TrialType<Info>) {
|
trial(display_element: HTMLElement, trial: TrialType<Info>) {
|
||||||
// create canvas
|
// Create canvas
|
||||||
var html =
|
const stimulusElement = document.createElement("div");
|
||||||
'<div id="jspsych-canvas-button-response-stimulus">' +
|
stimulusElement.id = "jspsych-canvas-button-response-stimulus";
|
||||||
'<canvas id="jspsych-canvas-stimulus" height="' +
|
|
||||||
trial.canvas_size[0] +
|
|
||||||
'" width="' +
|
|
||||||
trial.canvas_size[1] +
|
|
||||||
'"></canvas>' +
|
|
||||||
"</div>";
|
|
||||||
|
|
||||||
//display buttons
|
const canvasElement = document.createElement("canvas");
|
||||||
var buttons = [];
|
canvasElement.id = "jspsych-canvas-stimulus";
|
||||||
if (Array.isArray(trial.button_html)) {
|
canvasElement.height = trial.canvas_size[0];
|
||||||
if (trial.button_html.length == trial.choices.length) {
|
canvasElement.width = trial.canvas_size[1];
|
||||||
buttons = trial.button_html;
|
stimulusElement.appendChild(canvasElement);
|
||||||
} 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>";
|
|
||||||
|
|
||||||
//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) {
|
if (trial.prompt !== null) {
|
||||||
html += trial.prompt;
|
display_element.insertAdjacentHTML("beforeend", trial.prompt);
|
||||||
}
|
}
|
||||||
display_element.innerHTML = html;
|
|
||||||
|
|
||||||
//draw
|
//draw
|
||||||
let c = document.getElementById("jspsych-canvas-stimulus");
|
trial.stimulus(canvasElement);
|
||||||
trial.stimulus(c);
|
|
||||||
|
|
||||||
// start time
|
// start time
|
||||||
var start_time = performance.now();
|
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
|
// store response
|
||||||
var response = {
|
var response = {
|
||||||
rt: null,
|
rt: null,
|
||||||
@ -186,14 +167,11 @@ class CanvasButtonResponsePlugin implements JsPsychPlugin<Info> {
|
|||||||
|
|
||||||
// after a valid response, the stimulus will have the CSS class 'responded'
|
// 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
|
// which can be used to provide visual feedback that a response was recorded
|
||||||
display_element.querySelector("#jspsych-canvas-button-response-stimulus").className +=
|
stimulusElement.classList.add("responded");
|
||||||
" responded";
|
|
||||||
|
|
||||||
// disable all the buttons after a response
|
// disable all the buttons after a response
|
||||||
var btns = document.querySelectorAll(".jspsych-canvas-button-response-button button");
|
for (const button of buttonGroupElement.children) {
|
||||||
for (var i = 0; i < btns.length; i++) {
|
button.setAttribute("disabled", "disabled");
|
||||||
//btns[i].removeEventListener('click');
|
|
||||||
btns[i].setAttribute("disabled", "disabled");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (trial.response_ends_trial) {
|
if (trial.response_ends_trial) {
|
||||||
@ -204,9 +182,7 @@ class CanvasButtonResponsePlugin implements JsPsychPlugin<Info> {
|
|||||||
// hide image if timing is set
|
// hide image if timing is set
|
||||||
if (trial.stimulus_duration !== null) {
|
if (trial.stimulus_duration !== null) {
|
||||||
this.jsPsych.pluginAPI.setTimeout(() => {
|
this.jsPsych.pluginAPI.setTimeout(() => {
|
||||||
display_element.querySelector<HTMLElement>(
|
stimulusElement.style.visibility = "hidden";
|
||||||
"#jspsych-canvas-button-response-stimulus"
|
|
||||||
).style.visibility = "hidden";
|
|
||||||
}, trial.stimulus_duration);
|
}, trial.stimulus_duration);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -262,7 +238,9 @@ class CanvasButtonResponsePlugin implements JsPsychPlugin<Info> {
|
|||||||
|
|
||||||
if (data.rt !== null) {
|
if (data.rt !== null) {
|
||||||
this.jsPsych.pluginAPI.clickTarget(
|
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
|
data.rt
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user