Core
- Overview
- Survey Constructor
- Elements
- Logic
- Plugins
Support
Core
Logic
RoundtableJS uses JavaScript’s async/await
syntax for handling asynchronous operations. Here’s a basic example:
async function runSurvey() {
const survey = new Survey({ participantId: 'participant_123' });
// This line waits for the page to be shown and answered
await survey.showPage({ id: 'page1', elements: [question1] });
// This code runs only after page1 is completed
console.log('Page 1 completed');
// Show the next page
await survey.showPage({ id: 'page2', elements: [question2] });
survey.finishSurvey();
}
// Start the survey
runSurvey();
In this example, await
pauses execution until each page is completed, allowing for a linear programming schema that represents the survey flow.
Why Async for Surveys?
Surveys involve multiple time-consuming operations:
- Waiting for user input
- Fetching data from a server
- Performing calculations for branching logic
Basic Logic
Conditional Logic: Show or hide questions based on previous responses
async function runSurvey() {
const survey = new Survey({ participantId: 'participant_123' });
const q1 = new SingleSelect({
id: 'pet_preference',
text: 'Which pet do you prefer?',
options: ['Dog', 'Cat', 'Neither']
});
await survey.showPage({ id: 'page1', elements: [q1] });
// Conditional logic: Only show follow-up question if 'Neither' wasn't selected
if (survey.getResponse('pet_preference') !== 'Neither') {
const q2 = new OpenEnd({
id: 'pet_reason',
text: `Why do you prefer ${survey.getResponse('pet_preference')}s?`
});
await survey.showPage({ id: 'page2', elements: [q2] });
}
survey.finishSurvey();
}
Skip Logic: Skip entire pages based on responses
async function runSurvey() {
const survey = new Survey({ participantId: 'participant_123' });
// First page with age question
const ageQuestion = new NumberEntry({
id: 'age',
text: 'What is your age?',
min: 1,
max: 120
});
await survey.showPage({ id: 'age_page', elements: [ageQuestion] });
// Skip logic based on age
if (survey.getResponse('age') >= 18) {
await showAdultQuestions(survey);
} else {
await showMinorQuestions(survey);
}
survey.finishSurvey();
}
async function showAdultQuestions(survey) {
// Implementation of adult-specific questions
}
async function showMinorQuestions(survey) {
// Implementation of minor-specific questions
}
Piping: Use previous responses in subsequent questions
async function runSurvey() {
const survey = new Survey({ participantId: 'participant_123' });
// First question about pet preference
const q1 = new SingleSelect({
id: 'pet_preference',
text: 'Which pet do you prefer?',
options: ['Dog', 'Cat', 'Fish']
});
await survey.showPage({ id: 'page1', elements: [q1] });
// Piping the response into the next question
const favoritePet = survey.getResponse('pet_preference');
const q2 = new OpenEnd({
id: 'pet_description',
text: `Describe your ideal ${favoritePet}.`
});
await survey.showPage({ id: 'page2', elements: [q2] });
survey.finishSurvey();
}
Advanced Logic
Complex Branching: Set branching criteria based on multiple conditions
async function runSurvey() {
const survey = new Survey({ participantId: 'participant_123' });
// Collect demographic information
await collectDemographics(survey);
const age = survey.getResponse('age');
const income = survey.getResponse('income');
const education = survey.getResponse('education');
// Complex branching based on multiple criteria
if (age > 30 && income > 50000 && education === 'Bachelor\'s or higher') {
await showHighValueCustomerQuestions(survey);
} else if (age <= 30 && income <= 30000) {
await showYoungBudgetCustomerQuestions(survey);
} else {
await showGeneralCustomerQuestions(survey);
}
survey.finishSurvey();
}
async function collectDemographics(survey) {
// Implementation of demographic questions
}
async function showHighValueCustomerQuestions(survey) {
// Questions for high-value customers
}
async function showYoungBudgetCustomerQuestions(survey) {
// Questions for young budget-conscious customers
}
async function showGeneralCustomerQuestions(survey) {
// General customer questions
}
Looping: Circle through repetitive question sets for multiple options
async function runSurvey() {
const survey = new Survey({ participantId: 'participant_123' });
const numberOfProducts = await askNumberOfProducts(survey);
// Loop through product questions
for (let i = 0; i < numberOfProducts; i++) {
await askProductQuestions(survey, i + 1);
}
survey.finishSurvey();
}
async function askNumberOfProducts(survey) {
const q = new NumberEntry({
id: 'num_products',
text: 'How many products do you want to rate?',
min: 1,
max: 5
});
await survey.showPage({ id: 'num_products_page', elements: [q] });
return survey.getResponse('num_products');
}
async function askProductQuestions(survey, productNumber) {
const q1 = new SingleSelect({
id: `product_${productNumber}_rating`,
text: `How would you rate product ${productNumber}?`,
options: ['Poor', 'Fair', 'Good', 'Excellent']
});
const q2 = new OpenEnd({
id: `product_${productNumber}_feedback`,
text: `Any additional feedback for product ${productNumber}?`
});
await survey.showPage({ id: `product_${productNumber}_page`, elements: [q1, q2] });
}
Quota Management: Implement quotas to limit responses based on certain criteria
async function checkAndUpdateQuota(age, gender) {
// This function would typically involve a server call to check and update quotas
// For this example, we'll simulate it with a local check
const quotaFilled = await simulateQuotaCheck(age, gender);
if (quotaFilled) {
throw new Error('QUOTA_FILLED');
}
}
async function simulateQuotaCheck(age, gender) {
// Simulate a server call with a random result
await new Promise(resolve => setTimeout(resolve, 1000)); // Simulate network delay
return Math.random() < 0.2; // 20% chance the quota is filled
}
async function conductMainSurvey(survey) {
// Implementation of the main survey questions
}
async function runSurvey() {
const survey = new Survey({ participantId: 'participant_123' });
// Collect demographic information
await collectDemographics(survey);
const age = survey.getResponse('age');
const gender = survey.getResponse('gender');
try {
// Check if the quota for this demographic is filled
await checkAndUpdateQuota(age, gender);
} catch (error) {
if (error.message === 'QUOTA_FILLED') {
survey.finishSurvey({ message: 'Thank you, but our quota for your demographic has been filled.' });
return;
}
// Handle other errors
console.error('Error checking quota:', error);
survey.finishSurvey({ error: 'An unexpected error occurred.' });
return;
}
// Continue with the survey if quota is not filled
await conductMainSurvey(survey);
survey.finishSurvey();
}
On this page