diff --git a/docs/plugins/survey.md b/docs/plugins/survey.md index b429e73b..97ab9598 100644 --- a/docs/plugins/survey.md +++ b/docs/plugins/survey.md @@ -94,7 +94,7 @@ In addition to the [default data collected by all plugins](../overview/plugins.m Name | Type | Value -----|------|------ -response | object | An object containing the response to each question. The object will have a separate key (variable) for each question, with the first question on the first page being recorded in `P0_Q0`, the second question on the first page in `P0_Q1`, and so on. If the `name` parameter is defined for the question, then the response object will use the value of `name` as the key for each question. The response type will depend on the question type. This will be encoded as a JSON string when data is saved using the `.json()` or `.csv()` functions. | +response | object | An object containing the response to each question. The object will have a separate key (variable) for each question, with the first question on the first page being recorded in `P0_Q0`, the second question on the first page in `P0_Q1`, and so on. If the `name` parameter is defined for the question, then the response object will use the value of `name` as the key for each question. The response type will depend on the question type. This will be encoded as a JSON string when data is saved using the `.json()` or `.csv()` functions. Note that, if any questions use the `other` option (`add_other_option: true`), then the response value will be the `other_option_text` (e.g. "Other") and any text written in the textbox will be saved as "(question name)-Comment". | rt | numeric | The response time in milliseconds for the subject to make a response. The time is measured from when the questions first appear on the screen until the subject's response(s) are submitted. | question_order | array | An array with the order of questions. For example `[2,0,1]` would indicate that the first question was `trial.questions[2]` (the third item in the `questions` parameter), the second question was `trial.questions[0]`, and the final question was `trial.questions[1]`. This will be encoded as a JSON string when data is saved using the `.json()` or `.csv()` functions. | diff --git a/packages/plugin-survey/example.html b/packages/plugin-survey/example.html index 4e207e92..bb7b7f62 100644 --- a/packages/plugin-survey/example.html +++ b/packages/plugin-survey/example.html @@ -28,7 +28,7 @@ [ {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: 'multi-choice', prompt: 'This is a multi-choice question with options in two columns, with an "other" option.', options: options, columns: 2, add_other_option: true}, {type: 'html', prompt: '

Another HTML question type.
Don't forget to answer the next question!

'}, {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'}, diff --git a/packages/plugin-survey/src/index.ts b/packages/plugin-survey/src/index.ts index 2edd0b53..5ccfb466 100644 --- a/packages/plugin-survey/src/index.ts +++ b/packages/plugin-survey/src/index.ts @@ -1,5 +1,5 @@ import { JsPsych, JsPsychPlugin, ParameterType, TrialType } from "jspsych"; -import { QuestionComment, StylesManager, Survey } from "survey-knockout"; +import { QuestionComment, QuestionRadiogroup, StylesManager, Survey } from "survey-knockout"; import { require } from "yargs"; const info = { @@ -62,6 +62,22 @@ const info = { pretty_name: "Columns", default: 1, }, + /** + * Multi-choice/multi-select only: Whether or not to include an additional "other" option. + * If true, an "other" radio/checkbox option will be added on to the list multi-choice/multi-select options. + * Selecting this option will automatically produce a textbox to allow the participant to write in a response. + */ + add_other_option: { + type: ParameterType.BOOL, + pretty_name: "Add other option", + default: false, + }, + /** Multi-choice/multi-select only: If add_other_option is true, then this is the text label for the "other" option. */ + other_option_text: { + type: ParameterType.BOOL, + pretty_name: "Other option text", + default: "Other", + }, /** Text only: Placeholder text in the response text box. */ placeholder: { type: ParameterType.STRING, @@ -185,6 +201,8 @@ class SurveyPlugin implements JsPsychPlugin { "options", "option_reorder", "columns", + "add_other_option", + "other_option_text", ]); private multiselect_params = this.all_question_params.concat([ "options", @@ -412,7 +430,7 @@ class SurveyPlugin implements JsPsychPlugin { private setup_multichoice_question = (question, question_params) => { const req = ["options"]; - const opt = ["columns", "option_reorder"]; + const opt = ["columns", "option_reorder", "add_other_option", "other_option_text"]; this.validate_question_params( this.all_question_params_req.concat(req), this.all_question_params_opt.concat(opt), @@ -423,6 +441,10 @@ class SurveyPlugin implements JsPsychPlugin { question.title = question_params.prompt; question.isRequired = question_params.required; + question.hasOther = question_params.add_other_option; + if (question.hasOther) { + question.otherText = question_params.other_option_text; + } question.choices = question_params.options; if (typeof question_params.option_reorder == "undefined") { question.choicesOrder = info.parameters.pages.nested.option_reorder.default; @@ -430,7 +452,11 @@ class SurveyPlugin implements JsPsychPlugin { question.choicesOrder = question_params.option_reorder; } question.colCount = question_params.columns; - question.defaultValue = ""; + if (question instanceof QuestionRadiogroup) { + question.defaultValue = ""; + } else { + question.defaultValue = []; // multi-select/checkbox + } return question; };