mirror of
https://github.com/jspsych/jsPsych.git
synced 2025-05-10 19:20:55 +00:00
add different question types/params, survey-level params, expand example file (WIP)
This commit is contained in:
parent
a073b07f2a
commit
c45cd249e3
@ -3,7 +3,8 @@
|
||||
<head>
|
||||
<script src="../jspsych/dist/index.browser.js"></script>
|
||||
<script src="./dist/index.browser.js"></script>
|
||||
<link rel="stylesheet" href="../jspsych/css/jspsych.css"></script>
|
||||
<link rel="stylesheet" href="../jspsych/css/jspsych.css">
|
||||
<link rel="stylesheet" href="css/plugin-survey.css">
|
||||
</head>
|
||||
<body></body>
|
||||
<script type="text/javascript">
|
||||
@ -14,26 +15,46 @@
|
||||
}
|
||||
});
|
||||
|
||||
var options = ['option 1', 'option 2', 'option 3', 'option 4', 'option 5', 'option 6'];
|
||||
|
||||
var survey_trial = {
|
||||
type: jsPsychSurvey,
|
||||
pages: [
|
||||
[
|
||||
{type: 'html', prompt: '<p>Here is some arbitrary text via an "html" question type.<br>Similar to preamble but can be inserted anywhere in the question set.</p>'},
|
||||
{type: 'text', prompt: 'Page 1, question 1.'},
|
||||
{type: 'text', prompt: 'Page 1, question 2.'},
|
||||
{type: 'html', prompt: '<p>Here is some arbitrary text via an "html" question type.<br>Similar to preamble but can be inserted anywhere in the question set.<br>This trial uses automatic question numbering (continued across pages).</p>'},
|
||||
{type: 'text', prompt: 'This is a single-line text question.', rows: 1, columns: 20},
|
||||
{type: 'text', prompt: 'This is a multi-line text question.', placeholder: 'This is a placeholder.', rows: 5, columns: 40},
|
||||
],
|
||||
[
|
||||
{type: 'text', prompt: 'Page 2, question 1.'},
|
||||
{type: 'html', prompt: '<p>Don't forget to answer the next question!</p>'},
|
||||
{type: 'text', prompt: 'Page 2, question 2.'},
|
||||
{type: 'multi-choice', prompt: 'This is a multi-choice question with options in one column (the default).', options: options},
|
||||
{type: 'multi-choice', prompt: 'This is a multi-choice question with options in one row.', options: options, columns: 0},
|
||||
{type: 'multi-choice', prompt: 'This is a multi-choice question with options in two columns.', options: options, columns: 2},
|
||||
{type: 'html', prompt: '<p>Another HTML question type.<br>Don't forget to answer the next question!</p>'},
|
||||
{type: 'multi-select', prompt: 'This is a multi-select question.', options: options},
|
||||
{type: 'multi-select', prompt: 'This is a multi-select question with three columns and random option ordering.', options: options, columns: 3, option_reorder: 'random'},
|
||||
]
|
||||
],
|
||||
button_label_next: "Next >",
|
||||
button_label_back: "< Back",
|
||||
button_label_finish: "Finish!",
|
||||
show_question_numbers: 'on'
|
||||
};
|
||||
|
||||
jsPsych.run([survey_trial]);
|
||||
var survey_trial_random = {
|
||||
type: jsPsychSurvey,
|
||||
pages: [[
|
||||
{type: 'text', prompt: 'Question 1.', rows: 1, columns: 20},
|
||||
{type: 'text', prompt: 'Question 2.', rows: 1, columns: 20},
|
||||
{type: 'text', prompt: 'Question 3.', rows: 1, columns: 20},
|
||||
{type: 'text', prompt: 'Question 4.', rows: 1, columns: 20},
|
||||
{type: 'text', prompt: 'Question 5.', rows: 1, columns: 20},
|
||||
{type: 'text', prompt: 'Question 6.', rows: 1, columns: 20},
|
||||
]],
|
||||
title: 'This is a separate survey trial. The order of questions should be randomized.',
|
||||
randomize_question_order: true
|
||||
};
|
||||
|
||||
jsPsych.run([survey_trial, survey_trial_random]);
|
||||
|
||||
</script>
|
||||
</html>
|
@ -15,17 +15,17 @@ const info = <const>{
|
||||
type: ParameterType.SELECT,
|
||||
pretty_name: "Type",
|
||||
default: null, //undefined,
|
||||
options: ["html", "text"], // TO DO: other types
|
||||
options: ["html", "text", "multi-choice", "multi-select"], // TO DO: other types
|
||||
},
|
||||
/** Question prompt. */
|
||||
prompt: {
|
||||
type: ParameterType.HTML_STRING,
|
||||
pretty_name: "Prompt",
|
||||
default: null, //undefined,
|
||||
default: null, // TO DO: undefined for HTML questions
|
||||
},
|
||||
/** Whether or not a response to this question must be given in order to continue. */
|
||||
required: {
|
||||
type: ParameterType.BOOL, // TO DO
|
||||
type: ParameterType.BOOL,
|
||||
pretty_name: "Required",
|
||||
default: false,
|
||||
},
|
||||
@ -35,44 +35,47 @@ const info = <const>{
|
||||
pretty_name: "Question Name",
|
||||
default: "",
|
||||
},
|
||||
/** Multi-choice only: Array of strings that contains the set of multiple choice options to display for the question. */
|
||||
/** Multi-choice/multi-select only: Array of strings that contains the set of multiple choice options to display for the question. */
|
||||
options: {
|
||||
type: ParameterType.STRING, // TO DO
|
||||
type: ParameterType.STRING,
|
||||
pretty_name: "Options",
|
||||
default: null, // TO DO: how to make this undefined for certain question types?
|
||||
default: null, // TO DO: undefined for multi-choice/multi-select
|
||||
array: true,
|
||||
},
|
||||
/** Multi-choice only: If true, then the question is centered and the options are displayed horizontally. */
|
||||
horizontal: {
|
||||
type: ParameterType.BOOL, // TO DO
|
||||
pretty_name: "Horizontal",
|
||||
default: false,
|
||||
/** Multi-choice/multi-select only: re-ordering of options array */
|
||||
option_reorder: {
|
||||
type: ParameterType.SELECT,
|
||||
pretty_name: "Option reorder",
|
||||
options: ["none", "asc", "desc", "random"],
|
||||
default: "none",
|
||||
},
|
||||
/** Text only: Placeholder text in the response text box. */
|
||||
placeholder: {
|
||||
type: ParameterType.STRING, // TO DO
|
||||
type: ParameterType.STRING,
|
||||
pretty_name: "Placeholder",
|
||||
default: "",
|
||||
},
|
||||
/** Text only: The number of rows for the response text box. */
|
||||
rows: {
|
||||
type: ParameterType.INT, // TO DO
|
||||
type: ParameterType.INT,
|
||||
pretty_name: "Rows",
|
||||
default: 1,
|
||||
},
|
||||
/** Text only: The number of columns for the response text box. */
|
||||
/**
|
||||
* Text: The number of columns for the response text box.
|
||||
* Multi-choice/multi-select: The number of columns
|
||||
*/
|
||||
columns: {
|
||||
type: ParameterType.INT, // TO DO
|
||||
type: ParameterType.INT,
|
||||
pretty_name: "Columns",
|
||||
default: 40,
|
||||
},
|
||||
},
|
||||
},
|
||||
/** If true, the order of the questions in each of the 'pages' arrays will be randomized. */
|
||||
/** Whether or not to randomize the question order on each page */
|
||||
randomize_question_order: {
|
||||
// TO DO
|
||||
type: ParameterType.BOOL,
|
||||
pretty_name: "Randomize order",
|
||||
pretty_name: "Randomize question order",
|
||||
default: false,
|
||||
},
|
||||
/** Label of the button to move forward thorugh survey pages. */
|
||||
@ -112,6 +115,15 @@ const info = <const>{
|
||||
default: "off",
|
||||
options: ["on", "onPage", "off"],
|
||||
},
|
||||
/**
|
||||
* HTML-formatted text to be shown at the top of the survey pages. This also provides a method for fixing any arbitrary text to the top of the page when
|
||||
* randomizing the question order, since HTML question types are also randomized.
|
||||
*/
|
||||
title: {
|
||||
type: ParameterType.HTML_STRING,
|
||||
pretty_name: "Title",
|
||||
default: null,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@ -135,7 +147,7 @@ class SurveyPlugin implements JsPsychPlugin<Info> {
|
||||
// https://surveyjs.io/Examples/Library/?id=custom-theme
|
||||
}
|
||||
|
||||
// keys as strings so that the question types can have hyphens
|
||||
// map jsPsych question types onto SurveyJS question types (keys as strings so that the question types can have hyphens)
|
||||
readonly question_type_map: { [key: string]: string } = {
|
||||
"drop-down": "dropdown",
|
||||
html: "html",
|
||||
@ -147,17 +159,62 @@ class SurveyPlugin implements JsPsychPlugin<Info> {
|
||||
text: "text",
|
||||
};
|
||||
|
||||
// TO DO:
|
||||
// - move the setup functions outside of the trial method?
|
||||
// - fix the question row spacing CSS
|
||||
// - add other and none options to multi-choice/select
|
||||
trial(display_element: HTMLElement, trial: TrialType<Info>) {
|
||||
this.applyStyles();
|
||||
this.applyStyles(); // applies bootstrap theme
|
||||
|
||||
// apply jsPsych CSS
|
||||
// TO DO: add CSS class for question prompts etc., need a new class for this (jspsych-display-element adds other stuff that causes problems)
|
||||
// add to this object in a modular way (by question type)?
|
||||
// add custom CSS classes to survey elements
|
||||
// https://surveyjs.io/Examples/Library/?id=survey-customcss&platform=Knockoutjs&theme=bootstrap#content-docs
|
||||
const jspsych_css = {
|
||||
question: {
|
||||
title: "jspsych-display-element",
|
||||
title: "jspsych-survey-question-prompt",
|
||||
},
|
||||
navigationButton: "jspsych-btn",
|
||||
html: {
|
||||
root: "jspsych-survey-html",
|
||||
},
|
||||
navigationButton: "jspsych-btn jspsych-survey-btn",
|
||||
};
|
||||
|
||||
// functions for setting up different question types
|
||||
const setup_dropdown_question = () => {};
|
||||
const setup_html_question = (question, question_params) => {
|
||||
// required: prompt
|
||||
question.html = question_params.prompt;
|
||||
return question;
|
||||
};
|
||||
const setup_likert_question = () => {};
|
||||
const setup_multichoice_question = (question, question_params) => {
|
||||
// required: options
|
||||
// optional: columns, option_reorder
|
||||
question.title = question_params.prompt;
|
||||
question.isRequired = question_params.required;
|
||||
question.choices = question_params.options;
|
||||
if (typeof question_params.option_reorder == "undefined") {
|
||||
question.choicesOrder = info.parameters.pages.nested.option_reorder.default; // TO DO: is this how to get the default value from parameter info?
|
||||
} else {
|
||||
question.choicesOrder = question_params.option_reorder;
|
||||
}
|
||||
question.colCount = question_params.columns;
|
||||
return question;
|
||||
};
|
||||
|
||||
const setup_ranking_question = () => {};
|
||||
const setup_rating_question = () => {};
|
||||
const setup_text_question = (question, question_params) => {
|
||||
// optional: placeholder, rows, columns
|
||||
question.title = question_params.prompt;
|
||||
question.isRequired = question_params.required;
|
||||
question.placeHolder = question_params.placeholder;
|
||||
if (question.type == "comment") {
|
||||
question.rows = question_params.rows;
|
||||
question.cols = question_params.columns;
|
||||
} else {
|
||||
question.size = question_params.columns;
|
||||
}
|
||||
return question;
|
||||
};
|
||||
|
||||
// https://surveyjs.io/Documentation/Library#survey-objects
|
||||
@ -172,27 +229,57 @@ class SurveyPlugin implements JsPsychPlugin<Info> {
|
||||
// page numbers
|
||||
survey.showQuestionNumbers = trial.show_question_numbers;
|
||||
|
||||
// survey title
|
||||
if (trial.title !== null) {
|
||||
survey.title = trial.title;
|
||||
}
|
||||
|
||||
// pages and questions
|
||||
for (let i = 0; i < trial.pages.length; i++) {
|
||||
let page_id = "page" + i.toString();
|
||||
let page = survey.addNewPage(page_id);
|
||||
if (trial.randomize_question_order) {
|
||||
page.questionsOrder = "random"; // TO DO: save question presentation order to data
|
||||
}
|
||||
for (let j = 0; j < trial.pages[i].length; j++) {
|
||||
// TO DO: move question set-up to modular question-type methods
|
||||
let q_type = this.question_type_map[trial.pages[i][j].type];
|
||||
if (q_type == "text" && trial.pages[i][j].rows > 1) {
|
||||
let question_params = trial.pages[i][j];
|
||||
let q_type = this.question_type_map[question_params.type];
|
||||
if (q_type == "text" && question_params.rows > 1) {
|
||||
q_type = "comment";
|
||||
}
|
||||
let question = page.addNewQuestion(q_type);
|
||||
question.name = "p" + i.toString() + "_q" + j.toString();
|
||||
if (q_type == "html") {
|
||||
question.html = trial.pages[i][j].prompt;
|
||||
} else {
|
||||
question.title = trial.pages[i][j].prompt;
|
||||
switch (q_type) {
|
||||
case "comment": // text (multiple rows)
|
||||
setup_text_question(question, question_params);
|
||||
break;
|
||||
case "dropdown":
|
||||
break;
|
||||
case "html":
|
||||
setup_html_question(question, question_params);
|
||||
break;
|
||||
case "matrix": // likert
|
||||
break;
|
||||
case "radiogroup": // multi-choice
|
||||
setup_multichoice_question(question, question_params);
|
||||
break;
|
||||
case "checkbox": // multi-select
|
||||
setup_multichoice_question(question, question_params);
|
||||
break;
|
||||
case "ranking": // ranking
|
||||
break;
|
||||
case "rating": // rating
|
||||
break;
|
||||
case "text": // text (single row)
|
||||
setup_text_question(question, question_params);
|
||||
break;
|
||||
default:
|
||||
console.error('Error in survey plugin: invalid question type "', q_type, '"');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// set up survey structure via JS object
|
||||
// for reference: how to set up survey structure via JS object
|
||||
// var json = {
|
||||
// pages: [
|
||||
// {
|
||||
|
Loading…
Reference in New Issue
Block a user