Created
February 26, 2018 00:14
-
-
Save mkopinsky/3424d56b96ce751b3d67230f9e5ae8a9 to your computer and use it in GitHub Desktop.
Survey Editor overrides for usability
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Attach the surveyjs editor to a div on the page | |
* | |
* @param string el jquery selector for the place to attach the editor | |
* @param object initialValue the current schema for the survey | |
* @param function saveSchemaCallback Callback to be called each time the survey schema is modified | |
*/ | |
function attachSurveyEditor(el, initialValue, saveSchemaCallback) { | |
var editor = new SurveyEditor.SurveyEditor(el, editorOptions); | |
editor.text = JSON.stringify(initialValue); | |
editor.onModified.add(function() { | |
saveSchemaCallback(editor.getSurveyJSON()); | |
}); | |
// Call the callback right away as well | |
saveSchemaCallback(editor.getSurveyJSON()); | |
// Add our user-defined questions, and clear out the prior items | |
editor.toolbox.addItems(getQuestionTypes(editor), true); | |
// Hide the apply button | |
editor.showApplyButtonInEditors = false; | |
// Get rid of the 'Add to toolbox' menu item | |
// https://github.com/surveyjs/editor/issues/195 | |
editor.onDefineElementMenuItems.add(function(editor, options) { | |
options.items.splice(0, 1); | |
}); | |
// Prevent users from creating multiple questions with the same name | |
editor.onPropertyValidationCustomError.add(function(editor, options) { | |
if(options.propertyName != "name") return; | |
var otherQuestionNames = editor.getAllQuestions().filter(function(question) { | |
return question != options.obj; | |
}).map(function(question) { | |
return question.name; | |
}); | |
if (otherQuestionNames.indexOf(options.value) != -1) { | |
options.error = 'Question IDs must be unique in the survey. You already have a question named '+options.value; | |
} | |
}); | |
// Prevent users from creating a question with too long a name | |
editor.onPropertyValidationCustomError.add(function(editor, options) { | |
console.log(options.propertyName); | |
if(options.propertyName != "name") return; | |
var questionName = options.value; | |
if (questionName.length > 60) { | |
options.error = 'The question ID is limited to 60 characters. Please use the question text below if you need more space.' | |
return; | |
} | |
if (options.obj.choices) { | |
var longestChoiceValue = Math.max.apply(null, | |
options.obj.choices.map(function(choice) { | |
return choice.itemValue.length; | |
}) | |
); | |
if (longestChoiceValue > 60) { | |
options.error = 'Choice coding values are limited to 60 characters. Please use the display value if you need more space.' | |
return; | |
} | |
} | |
if (options.obj.rowsValue) { | |
var longestMatrixRow = Math.max.apply(null, | |
options.obj.rowsValue.map(function(row) { | |
return row.itemValue.length; | |
}) | |
); | |
if (longestMatrixRow > 60) { | |
options.error = 'Matrix row codings are limited to 60 characters. Please use the display value if you need more space.' | |
return; | |
} | |
} | |
if (options.obj.columnsValue) { | |
var longestMatrixColumn = Math.max.apply(null, | |
options.obj.columnsValue.map(function(row) { | |
return row.itemValue.length; | |
}) | |
); | |
if (longestMatrixColumn > 60) { | |
options.error = 'Matrix column IDs are limited to 60 characters. Please use the question text if you need more space.' | |
return; | |
} | |
} | |
}); | |
} | |
// Set various SurveyEditor constants | |
Survey.Survey.cssType = "bootstrap"; | |
SurveyEditor.defaultStrings.pe.isRequired = 'Required'; | |
SurveyEditor.defaultStrings.pe.startWithNewLine = 'Start on new line'; | |
SurveyEditor.defaultStrings.pe.visible = 'Visible'; | |
SurveyEditor.defaultStrings.pe.tabs.html = 'Editor'; | |
SurveyEditor.defaultStrings.pe.tabs.visibleIf = 'Display Logic'; | |
SurveyEditor.defaultStrings.pe.name = 'Question ID *'; | |
SurveyEditor.defaultStrings.pe.title = 'Question text'; | |
SurveyEditor.defaultStrings.pe.value = 'Coding *'; | |
SurveyEditor.defaultStrings.pe.text = 'Display'; | |
SurveyEditor.defaultStrings.pe.hasOther = 'Add option for \'Other\''; | |
SurveyEditor.defaultStrings.pe.optionsCaption = 'Dropdown label (e.g. \'Choose...\')'; | |
// Change the question type strings globally. This affects how they show up in the | |
// toolbox, as well as in the "Convert to X" option in the question menu | |
SurveyEditor.defaultStrings.qt.text = "Text Box"; | |
SurveyEditor.defaultStrings.qt.comment = "Free Text Entry"; | |
SurveyEditor.defaultStrings.qt.html = "Instruction text"; | |
SurveyEditor.defaultStrings.qt.dropdown = "Multiple choice - Drop down"; | |
SurveyEditor.defaultStrings.qt.radiogroup = "Multiple choice - Radio buttons"; | |
SurveyEditor.defaultStrings.qt.checkbox = "Checkboxes (Multiple Answers)"; | |
SurveyEditor.defaultStrings.qt.rating = "Numeric Scale"; | |
SurveyEditor.defaultStrings.qt.matrix = "Matrix - Radio Buttons"; | |
SurveyEditor.defaultStrings.qt.panel = "Section"; | |
SurveyEditor.defaultStrings.survey.dropQuestion = "Please drop a question here from the toolbox on the left."; | |
// Get rid of choicesByUrl tab | |
Object.keys(SurveyEditor.SurveyQuestionEditorDefinition.definition).forEach(function(key) { | |
var section = SurveyEditor.SurveyQuestionEditorDefinition.definition[key]; | |
if (section.tabs) { | |
var tabIndex = section.tabs.findIndex(function (tab) { | |
return tab.name=='choicesByUrl'; | |
}); | |
if (tabIndex > -1) { | |
section.tabs.splice(tabIndex, 1); | |
} | |
} | |
}); | |
Survey.JsonObject.metaData.removeProperty("questionbase", "visible"); | |
Survey.JsonObject.metaData.removeProperty("questionbase", "startWithNewLine"); | |
var editorOptions = { | |
showEmbededSurveyTab : false, | |
showTestSurveyTab : true, | |
showJSONEditorTab : false, | |
showOptions: false, | |
showPropertyGrid: false, | |
}; | |
// Set up the ckeditor for HTML (aka instruction text questions) | |
var CkEditor_ModalEditor = { | |
afterRender: function(modalEditor, htmlElement) { | |
var editor = CKEDITOR.replace(htmlElement); | |
editor.on('change', function() { | |
modalEditor.editingValue = editor.getData(); | |
}); | |
editor.setData(modalEditor.editingValue); | |
}, | |
destroy: function(modalEditor, htmlElement) { | |
var instance = CKEDITOR.instances[htmlElement.id]; | |
if (instance){ | |
instance.removeAllListeners(); | |
CKEDITOR.remove(instance); | |
} | |
} | |
}; | |
SurveyEditor.SurveyPropertyModalEditor.registerCustomWidget("html", CkEditor_ModalEditor); | |
// Get the customized list of question types | |
function getQuestionTypes(editor) { | |
// The list of question types, most of which are just title overrides from the default | |
var questionTypes = [ | |
{ | |
name: 'panel', | |
}, | |
{ | |
name: 'html', | |
}, | |
{ | |
name: 'text', | |
}, | |
{ | |
name: 'comment', | |
}, | |
{ | |
name: 'dropdown', | |
}, | |
{ | |
name: 'radiogroup', | |
}, | |
{ | |
name: 'checkbox', | |
}, | |
{ | |
name: 'yesno', | |
title: 'Yes/No', | |
iconName: 'icon-dropdown', | |
json: { | |
type: 'dropdown', | |
name: 'q1', | |
choices: ['Yes', 'No'] | |
} | |
}, | |
{ | |
name: 'truefalse', | |
title: 'True/False', | |
iconName: 'icon-dropdown', | |
json: { | |
type: 'dropdown', | |
name: 'q1', | |
choices: ['True', 'False'] | |
} | |
}, | |
{ | |
name: 'rating', | |
}, | |
{ | |
name: 'matrix', | |
}, | |
{ | |
name: 'matrixdropdown' | |
} | |
]; | |
function getDefaultQuestion(name) { | |
var question = editor.toolbox.itemsValue.filter(function(item) { | |
return item.name === name; | |
}); | |
return question ? question[0] : null; | |
} | |
// Assemble a list of question types with all the relevant properties, by combining surveyjs's | |
// defaults with our overrides | |
var questions = questionTypes.map(function (questionType) { | |
var question = getDefaultQuestion(questionType.name) || {}; | |
// This would be easier with Object.assign, but it's not available in IE | |
Object.keys(questionType).forEach(function (prop) { | |
question[prop] = questionType[prop]; | |
}); | |
return question; | |
}); | |
return questions; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment