Update README and App.vue with detailed project specifications and input schema
This commit is contained in:
parent
b5926e868f
commit
d6e8ca4068
131
README.md
131
README.md
@ -1,29 +1,124 @@
|
||||
# js-exform
|
||||
## Introduction
|
||||
|
||||
This template should help get you started developing with Vue 3 in Vite.
|
||||
This project is to develop a Vue 3 single page questionnaire application to be embedded in online psychology experiments. Demo pages are hosted to show how it looks like:
|
||||
- [Standard](https://js-exform.pages.dev/demo)
|
||||
- [Dark mode](https://js-exform.pages.dev/demo-dark)
|
||||
- [Chinese version](https://js-exform.pages.dev/demo-cn)
|
||||
|
||||
## Recommended IDE Setup
|
||||
This project is still under active development and could be very unstable (due to skill issues).
|
||||
|
||||
[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur).
|
||||
The following parts of the documentation are generated by `Claude-3.7-Sonnet`.
|
||||
|
||||
## Customize configuration
|
||||
## Data Transport
|
||||
|
||||
See [Vite Configuration Reference](https://vite.dev/config/).
|
||||
The questionnaire component receives input via the `window.postMessage` API. The parent window should post a message with the following structure:
|
||||
|
||||
## Project Setup
|
||||
```javascript
|
||||
window.postMessage({
|
||||
type: 'spec',
|
||||
title: 'Your Questionnaire Title',
|
||||
items: [...], // Array of question items
|
||||
settings: {...} // Configuration options
|
||||
}, '*');
|
||||
```
|
||||
|
||||
## Input Schema
|
||||
|
||||
### Root Object
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|-------|------|----------|-------------|
|
||||
| type | string | Yes | Must be 'spec' |
|
||||
| title | string | Yes | Main title of the questionnaire |
|
||||
| items | array | Yes | Array of question items |
|
||||
| settings | object | No | Configuration options |
|
||||
|
||||
### Item Object
|
||||
|
||||
Each item in the `items` array represents a question with the following structure:
|
||||
|
||||
```javascript
|
||||
{
|
||||
type: 'text', // 'text', 'radio', 'checkbox', 'scale', 'display'
|
||||
title: 'Question text',
|
||||
desc: 'Optional description text with HTML support',
|
||||
key: 'unique_identifier', // Optional, defaults to title
|
||||
optTexts: ['Option 1', 'Option 2'], // For 'radio', 'checkbox', 'scale'
|
||||
optValues: ['value1', 'value2'], // For 'radio', 'checkbox', 'scale'
|
||||
required: true, // Whether answer is required
|
||||
minOpts: 1, // For 'checkbox', minimum options to select
|
||||
maxOpts: 3 // For 'checkbox', maximum options to select
|
||||
}
|
||||
```
|
||||
|
||||
#### Item Fields
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|-------|------|----------|-------------|
|
||||
| type | string | Yes | Question type: 'text', 'radio', 'checkbox', 'scale', or 'display' |
|
||||
| title | string | Yes | Question text |
|
||||
| desc | string | No | Additional descriptive text (supports HTML) |
|
||||
| key | string | No | Unique identifier (defaults to title if not provided) |
|
||||
| optTexts | array | Conditional | Array of option texts for 'radio', 'checkbox', 'scale' |
|
||||
| optValues | array | Conditional | Array of option values for 'radio', 'checkbox', 'scale' |
|
||||
| required | boolean | No | Whether an answer is required (default: false) |
|
||||
| minOpts | number | No | Minimum options to select for 'checkbox' (default: 1) |
|
||||
| maxOpts | number | No | Maximum options to select for 'checkbox' (default: total options) |
|
||||
|
||||
### Settings Object
|
||||
|
||||
```javascript
|
||||
{
|
||||
allowBack: true, // Allow navigation to previous questions
|
||||
allowAutoNext: true, // Auto-advance after selection for radio/scale
|
||||
darkMode: false, // Visual theme
|
||||
lang: 'en-US' // Language code
|
||||
}
|
||||
```
|
||||
|
||||
## Question Types
|
||||
|
||||
- **text**: Single-line text input
|
||||
- **radio**: Single-choice selection with radio buttons
|
||||
- **checkbox**: Multiple-choice selection with checkboxes
|
||||
- **scale**: Slider scale with labeled endpoints
|
||||
- **display**: Information display with no input required
|
||||
|
||||
## Response Format
|
||||
|
||||
When the questionnaire is completed, the component sends a message to the parent window:
|
||||
|
||||
```javascript
|
||||
{
|
||||
type: 'response',
|
||||
started: 1646120000000, // Timestamp when questionnaire started
|
||||
ended: 1646121000000, // Timestamp when questionnaire completed
|
||||
results: [
|
||||
{
|
||||
title: 'Question text',
|
||||
key: 'question_key',
|
||||
type: 'question_type',
|
||||
answer: 'user_response',
|
||||
answerText: 'Text representation of response',
|
||||
answerValue: 'Value representation of response',
|
||||
refilled: false, // Whether the answer was changed
|
||||
responseTime: 5000 // Time spent on question in milliseconds
|
||||
},
|
||||
// Additional question results...
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
Please refer to source code of demo files.
|
||||
|
||||
## For developers
|
||||
|
||||
To modify or build the component, simply follow the standard routine:
|
||||
|
||||
```sh
|
||||
npm install
|
||||
```
|
||||
|
||||
### Compile and Hot-Reload for Development
|
||||
|
||||
```sh
|
||||
npm run dev
|
||||
```
|
||||
|
||||
### Compile and Minify for Production
|
||||
|
||||
```sh
|
||||
npm run build
|
||||
```
|
||||
```
|
12
src/App.vue
12
src/App.vue
@ -4,18 +4,6 @@ import { isProxy } from 'vue';
|
||||
import { sprintf } from 'sprintf-js';
|
||||
import lang from './lang.js';
|
||||
|
||||
/*
|
||||
* Specification of item data structure:
|
||||
* {
|
||||
* type: string, // 'text', 'radio', 'checkbox', 'scale'
|
||||
* title: string,
|
||||
* optTexts: string[], // only for 'radio', 'checkbox', 'scale'
|
||||
* optValues: string[], // only for 'radio', 'checkbox', 'scale'
|
||||
* required: boolean, // whether the user must answer the question
|
||||
* answer: string, // user's answer, appended after user submits
|
||||
* refilled: boolean, // whether the user refilled the answer, appended after user submits
|
||||
* }
|
||||
*/
|
||||
const ITEM_TYPES = ['text', 'radio', 'checkbox', 'scale', 'display'];
|
||||
function isValidItem({ type, title, optTexts, optValues = null }) {
|
||||
if (!title || !ITEM_TYPES.includes(type)) {
|
||||
|
Loading…
Reference in New Issue
Block a user