exp-lookit-survey¶
Overview¶
Basic survey frame allowing researcher to specify question text and types.
If a participant returns to this frame after continuing, via a ‘Previous’ button on the next frame, then the values in this form are pre-filled.
AlpacaJS¶
This frame uses ember-cli-dynamic-forms as a wrapper for alpacajs, a powerful library for generating online forms. To specify the structure of your form (questions, answer types, validation), you provide a single ‘formSchema’ structure. The ‘formSchema’ consists of a ‘schema’ object and an ‘options’ object, described under Properties.
You can choose from any question types listed at http://www.alpacajs.org/documentation.html. In that documentation, you will see that each field type - e.g., Checkbox, Radio, Text - has some ‘Schema’ properties and some ‘Options’ properties. The properties under ‘Schema’ will be defined in the ‘schema’ object of your formSchema. The properties under ‘Options’ will be defined in the ‘options’ object of your formSchema.
Many question types allow you to easily validate answers. For instance, for a “number”
field you can set minimum and maximum values, and entries will automatically be
required to be numeric (http://www.alpacajs.org/docs/fields/number.html). You can also
either set required: true
in the schema->properties entry for this field OR set
validator: required-field
in the options->fields entry if you want to require that the
participant enters something. A validation error message will be displayed next to
any fields that fail validation checks and the participant will not be able to proceed until
these are addressed.
Alpacajs is fairly powerful, and you are essentially using it directly. In general, you can copy and paste any object passed to alpaca in the alpaca docs right in as your formSchema to see that example in action on Lookit. Not all features of alpaca are detailed here, but they can be used: e.g., advanced users can enter ‘views’ and ‘data’ in the formSchema to customize the layout of their forms and the initial data. A ‘dataSource’ may be specified under options to populate a question’s potential answers (e.g., to load a list of countries from some other source rather than hard-coding it, or to provide checkboxes with vocabulary items from an externally-defined inventory).
Formatting¶
Note that question titles are interpreted as HTML and can include images, audio/video elements, and inline CSS.
The form itself occupies a maximum of 800px horizontally and takes up 80% of the vertical height of the window (it will scroll to fit).
Conditional questions¶
You can use alpacajs’s “dependencies” functionality to set up fields that depend on other fields - e.g., asking if the child speaks any language besides English in the home and only if so displaying a dropdown to select the language(s), or asking if the child likes Elmo or Grover better and then asking a question specific to the preferred character. Or if you have questions only relevant to the birth mother of the child, you could ask if the participant is the birth mother and show those questions conditionally. See below for an example.
Ordering questions¶
By default, questions should be presented in the order they’re defined in your schema. If they are not, you can use the “order” option to arrange them; see the Alpaca docs.
Ordering options¶
By default, Alpaca sorts options alphabetically for fields with radio buttons or checkboxes.
That’s usually not what you want. Add "sort": false
under formSchema -> options ->
fields -> <your field> to list them in the order you define them.
Localization¶
You are responsible for writing your questions and answers in the appropriate language for your study. To localize the
validation messages (like “this field is required”), add locale
to a view
for your formSchema
as shown below:
"pet-survey": {
"kind": "exp-lookit-survey",
"formSchema": {
"schema": {
...
},
"options": {
...
},
"view": {
"locale": "ja_JP"
}
},
...
}
See the Alpaca docs for a list of available locales.
Current limitations¶
You are NOT able to provide custom functions (e.g. validators, custom dataSource functions) directly to the formSchema.
What it looks like¶

More general functionality¶
Below is information specific to this particular frame. There may also be available parameters, events recorded, and data collected that come from the following more general sources:
the base frame (things all frames do)
Examples¶
Simple pet survey¶
Here is an example of a reasonably simple survey using this frame:
"pet-survey": {
"kind": "exp-lookit-survey",
"formSchema": {
"schema": {
"type": "object",
"title": "Tell us about your pet!",
"properties": {
"age": {
"type": "integer",
"title": "Age",
"maximum": 200,
"minimum": 0,
"required": true
},
"name": {
"type": "string",
"title": "Name",
"required": true
},
"species": {
"enum": [
"dog",
"cat",
"fish",
"bird",
"raccoon"
],
"type": "string",
"title": "What type of animal?",
"default": ""
}
}
},
"options": {
"fields": {
"age": {
"numericEntry": true
},
"name": {
"placeholder": "a name..."
},
"species": {
"type": "radio",
"message": "Seriously, what species??",
"validator": "required-field",
"removeDefaultNone": true,
"sort": false
}
}
}
},
"nextButtonText": "Moving on..."
}
Conditional dependence: show a question based on the answer to another question¶
"language-survey": {
"kind": "exp-lookit-survey",
"formSchema": {
"schema": {
"type": "object",
"properties": {
"multilingual": {
"type": "string",
"title": "Is your child regularly exposed to any languages besides English?",
"enum": [
"Yes",
"No"
]
},
"languages": {
"type": "text",
"title": "What other languages is he or she learning?"
}
},
"dependencies": {
"languages": [
"multilingual"
]
}
},
"options": {
"fields": {
"multilingual": {
"type": "radio",
"message": "Please select an answer",
"validator": "required-field",
"sort": false,
"removeDefaultNone": true,
"order": 1
},
"languages": {
"type": "text",
"message": "Please write in an answer",
"validator": "required-field",
"dependencies": {
"multilingual": "Yes"
},
"order": 2
}
}
}
}
}
Reproducing the mood survey¶
And here is an example of re-implementing the exp-lookit-mood-questionnaire frame, using custom formatting, time-pickers, dependencies, and question groups.
"mood-survey": {
"kind": "exp-lookit-survey",
"formSchema": {
"view": {
"fields": {
"/child/happy": {
"templates": {
"control": "<div>{{#if options.leftLabel}}<label class='label-left'>{{{options.leftLabel}}}</label>{{/if}}{{#control}}{{/control}}{{#if options.rightLabel}}<label class='label-right'>{{{options.rightLabel}}}</label>{{/if}}</div>"
}
},
"/child/active": {
"templates": {
"control": "<div>{{#if options.leftLabel}}<label class='label-left'>{{{options.leftLabel}}}</label>{{/if}}{{#control}}{{/control}}{{#if options.rightLabel}}<label class='label-right'>{{{options.rightLabel}}}</label>{{/if}}</div>"
}
},
"/child/rested": {
"templates": {
"control": "<div>{{#if options.leftLabel}}<label class='label-left'>{{{options.leftLabel}}}</label>{{/if}}{{#control}}{{/control}}{{#if options.rightLabel}}<label class='label-right'>{{{options.rightLabel}}}</label>{{/if}}</div>"
}
},
"/child/healthy": {
"templates": {
"control": "<div>{{#if options.leftLabel}}<label class='label-left'>{{{options.leftLabel}}}</label>{{/if}}{{#control}}{{/control}}{{#if options.rightLabel}}<label class='label-right'>{{{options.rightLabel}}}</label>{{/if}}</div>"
}
},
"/parent/energetic": {
"templates": {
"control": "<div>{{#if options.leftLabel}}<label class='label-left'>{{{options.leftLabel}}}</label>{{/if}}{{#control}}{{/control}}{{#if options.rightLabel}}<label class='label-right'>{{{options.rightLabel}}}</label>{{/if}}</div>"
}
},
"/parent/parentHappy": {
"templates": {
"control": "<div>{{#if options.leftLabel}}<label class='label-left'>{{{options.leftLabel}}}</label>{{/if}}{{#control}}{{/control}}{{#if options.rightLabel}}<label class='label-right'>{{{options.rightLabel}}}</label>{{/if}}</div>"
}
},
"/parent/ontopofstuff": {
"templates": {
"control": "<div>{{#if options.leftLabel}}<label class='label-left'>{{{options.leftLabel}}}</label>{{/if}}{{#control}}{{/control}}{{#if options.rightLabel}}<label class='label-right'>{{{options.rightLabel}}}</label>{{/if}}</div>"
}
}
},
"layout": {
"bindings": {
"child": "#child",
"parent": "#parent",
"lastEat": "#lastEat",
"nextNap": "#nextNap",
"napWakeUp": "#napWakeUp",
"doingBefore": "#doingBefore",
"usualNapSchedule": "#usualNapSchedule"
},
"template": "<div class='row exp-text exp-lookit-mood-questionnaire'><h4>{{{options.formTitle}}}</h4><p>{{{options.introText}}}</p><div id='child'></div><div id='parent'></div><div id='napWakeUp'></div><div id='usualNapSchedule'></div><div id='nextNap'></div><div id='lastEat'></div><div id='doingBefore'></div></div>"
},
"parent": "bootstrap-edit"
},
"schema": {
"type": "object",
"properties": {
"child": {
"type": "object",
"title": "How is your CHILD feeling right now?",
"properties": {
"happy": {
"enum": [
"1",
"2",
"3",
"4",
"5",
"6",
"7"
],
"required": true
},
"active": {
"enum": [
"1",
"2",
"3",
"4",
"5",
"6",
"7"
],
"required": true
},
"rested": {
"enum": [
"1",
"2",
"3",
"4",
"5",
"6",
"7"
],
"required": true
},
"healthy": {
"enum": [
"1",
"2",
"3",
"4",
"5",
"6",
"7"
],
"required": true
}
}
},
"parent": {
"type": "object",
"title": "How are YOU feeling right now?",
"properties": {
"energetic": {
"enum": [
"1",
"2",
"3",
"4",
"5",
"6",
"7"
],
"required": true
},
"parentHappy": {
"enum": [
"1",
"2",
"3",
"4",
"5",
"6",
"7"
],
"required": true
},
"ontopofstuff": {
"enum": [
"1",
"2",
"3",
"4",
"5",
"6",
"7"
],
"required": true
}
}
},
"lastEat": {
"title": "About how long ago did your child last eat or drink?",
"required": true
},
"nextNap": {
"title": "About how much longer until his/her next nap (or bedtime)?",
"required": true
},
"napWakeUp": {
"title": "About how long ago did your child last wake up from sleep or a nap?",
"required": true
},
"doingBefore": {
"title": "What was your child doing before this?",
"required": true
},
"usualNapSchedule": {
"enum": [
"yes",
"no",
"yes-overdue"
],
"title": "Does your child have a usual nap schedule?",
"required": true
}
},
"dependencies": {
"nextNap": [
"usualNapSchedule"
]
}
},
"options": {
"fields": {
"child": {
"fields": {
"happy": {
"type": "radio",
"order": 3,
"vertical": false,
"leftLabel": "Fussy",
"fieldClass": "aligned-radio-group",
"rightLabel": "Happy",
"optionLabels": [
"",
"",
"",
"",
"",
"",
""
]
},
"active": {
"type": "radio",
"order": 4,
"vertical": false,
"leftLabel": "Calm",
"fieldClass": "aligned-radio-group",
"rightLabel": "Active",
"optionLabels": [
"",
"",
"",
"",
"",
"",
""
]
},
"rested": {
"type": "radio",
"order": 1,
"vertical": false,
"leftLabel": "Tired",
"fieldClass": "aligned-radio-group",
"rightLabel": "Rested",
"optionLabels": [
"",
"",
"",
"",
"",
"",
""
]
},
"healthy": {
"type": "radio",
"order": 2,
"vertical": false,
"leftLabel": "Sick",
"fieldClass": "aligned-radio-group",
"rightLabel": "Healthy",
"optionLabels": [
"",
"",
"",
"",
"",
"",
""
]
}
}
},
"parent": {
"fields": {
"energetic": {
"type": "radio",
"order": 1,
"vertical": false,
"leftLabel": "Tired",
"fieldClass": "aligned-radio-group",
"rightLabel": "Energetic",
"optionLabels": [
"",
"",
"",
"",
"",
"",
""
]
},
"parentHappy": {
"type": "radio",
"order": 3,
"vertical": false,
"leftLabel": "Upset",
"fieldClass": "aligned-radio-group",
"rightLabel": "Happy",
"optionLabels": [
"",
"",
"",
"",
"",
"",
""
]
},
"ontopofstuff": {
"type": "radio",
"order": 2,
"vertical": false,
"leftLabel": "Overwhelmed",
"fieldClass": "aligned-radio-group",
"rightLabel": "On top of things",
"optionLabels": [
"",
"",
"",
"",
"",
"",
""
]
}
}
},
"lastEat": {
"size": 10,
"type": "time",
"picker": {
"useCurrent": "day"
},
"dateFormat": "HH:mm",
"placeholder": "hours:minutes"
},
"nextNap": {
"size": 10,
"type": "time",
"picker": {
"useCurrent": "day"
},
"dateFormat": "HH:mm",
"placeholder": "hours:minutes",
"dependencies": {
"usualNapSchedule": "yes"
}
},
"napWakeUp": {
"size": 10,
"type": "time",
"picker": {
"useCurrent": "day"
},
"dateFormat": "HH:mm",
"placeholder": "hours:minutes"
},
"doingBefore": {
"type": "text",
"placeholder": "examples: having lunch, playing outside, going to the store with me"
},
"usualNapSchedule": {
"sort": false,
"type": "select",
"hideNone": false,
"noneLabel": "",
"optionLabels": [
"Yes",
"No",
"Yes, and he/she is already due for a nap"
],
"removeDefaultNone": false
}
},
"formTitle": "Mood Questionnaire",
"introText": "How are you two doing? We really want to know: we’re interested in how your child’s mood affects which sorts of surprising physical events he/she notices. You can help us find out what babies are really learning as they get older... and what they already knew, but weren’t calm and focused enough to show us!",
"hideInitValidationError": true
}
},
"nextButtonText": "Next"
}
Parameters¶
- showPreviousButton [Boolean |
true
] Whether to show a ‘previous’ button
- nextButtonText [String |
'Next'
] Text to display on the ‘next frame’ button
- formSchema [Object]
Object specifying the content of the form. This is in the same format as the example definition of the const ‘schema’ at http://toddjordan.github.io/ember-cli-dynamic-forms/#/demos/data: a schema and options are designated separately. Each field of the form must be defined in schema. Options may additionally be specified in options. This object has fields:
- schema
[Object] The schema defines the fields in this form. It has the following properties:
- type
[String] This MUST be the string
'object'
.- title
[String] A form title for display
- properties
[Object] An object defining the set of questions in this form and their associated data types, at minimum. Each key:value pair in this object is of the form
'FIELDNAME': {...}
. TheFIELDNAME
is something you select, likeage
; it should be unique within this form. The object contains at least ‘type’ and ‘title’ values, as well as any additional desired parameters that belong to the ‘Schema’ for the desired field described at http://www.alpacajs.org/documentation.html.
- options
[Object] The options allow additional customization of the forms specified in the schema. This object should have a single key ‘fields’ mapping to an object. Each key:value pair in this object is of the form FIELDNAME:object, with FIELDNAMEs the same as in the schema. The potential parameters to use are those that belong to the ‘Options’ for the desired field described at http://www.alpacajs.org/documentation.html.
Data collected¶
The fields added specifically for this frame type are:
- formSchema [Object]
The same formSchema that was provided as a parameter to this frame, for ease of analysis if randomizing or iterating on experimental design.
- formData [Object]
Data corresponding to the fields defined in formSchema[‘schema’][‘properties’]. The keys of formData are the FIELDNAMEs used there, and the values are the participant’s responses. Note that if the participant does not answer a question, that key may be absent, rather than being present with a null value.
Events recorded¶
No events are recorded specifically by this frame.