While overriding templates for question views and writing custom CSS for questions enables you to make extensive customisations, you can also add entirely new question types.
Make use of that feature when you want to:
Build custom behaviour on user interactions and system events
Leverage data from custom question properties
Control visual output and user interactions entirely
Files involved in creating a custom question type:
Every type has a name - for this article we use ‘customtype’.
A JS question type object in [customization_assets_folder]/javascript/custom_questions.js
A view class and template in [customization_folder]/views/question_customtype/view.html.php and [customization_folder]/views/question_customtype/tmpl/default.php
CSS styling in [customization_assets_folder]/css/custom.css
JS Question Type Object
Create the file [customization_assets_dir]/javascript/custom_questions.js. CB will automatically load this file if present (or a min.js file if present).
A JS Question Type Object (a plain JavaScript object) with a set of functions. and pass it as a parameter the function registerQuestion() of the ConfigBox AMD module configbox/configurator.
Example custom_questions.js
define(['cbj', 'configbox/configurator'], function(cbj, configurator) { // Custom question type object var customType = { // .. set of required methods (see below on this page) } // Replace Name_of_your_type with your type name configurator.registerQuestion('Name_of_your_type', customType); });
In this file you can register any number of question types.
Required methods in the JS Question Type Object:
init() - will run on page load and the function needs to initialise any JS-powered content in the question
initEach() - will run on page load AND each time the configurator view gets refreshed via AJAX calls
onSystemSelectionChange(event, questionId, selection) - runs when the system changes a selection (auto-selects, selection removals from rule engine, etc)
onQuestionActivation(event, questionId) - runs when the rule engine activates the question
onQuestionDeactivation(event, questionId) - runs when the rule engine deactivates the question
onAnswerActivation(event, questionId, answerId) - runs when the rule engine activates an answer of the question
onAnswerDeactivation(event, questionId, answerId) - runs when the rule engine deactivates an answer of the question
onValidationChange(event, questionId, validation) - runs when the validation engine alters validation settings for the question (calculation based min/max values)
onValidationMessageShown(event, questionId, message) - runs when the engine instructs to show a validation message for the question
onValidationMessageCleared(event, questionId) - runs when the engine instructs to hide a validation message for the question
Full example
define(['configbox/configurator'], function(configurator) { var customQuestionType = { /** * Will run on page load and the function needs to initialise any JS-powered content in the question */ init: function() { }, /** * Will run on page load AND each time the configurator view gets refreshed via AJAX calls */ initEach: function() { }, /** * runs when the system changes a selection (auto-selects, selection removals from rule engine, etc) * @param {Event} event * @param {Number} questionId * @param {String|NULL} selection - NULL on deselect, the internal selection value for the answer instead */ onSystemSelectionChange: function(event, questionId, selection) { }, /** * Runs when the rule engine activates the question * @param {Event} event * @param {Number} questionId */ onQuestionActivation: function(event, questionId) { }, /** * Runs when the rule engine deactivates the question * @param {Event} event * @param {Number} questionId */ onQuestionDeactivation: function(event, questionId) { }, /** * Runs when the rule engine activates an answer * @param {Event} event * @param {Number} questionId * @param {Number} answerId */ onAnswerActivation: function(event, questionId, answerId) { }, /** * Runs when the rule engine deactivates an answer * @param {Event} event * @param {Number} questionId * @param {Number} answerId */ onAnswerDeactivation: function(event, questionId, answerId) { }, /** * Runs when the validation engine changes validation for a question * @param {Event} event * @param {Number} questionId * @param {Object} validation - plain object with vars minval and maxval * values of each are either NULL for no validation or a number */ onValidationChange: function(event, questionId, validation) { }, /** * Runs when the engine instructs to show a validation message * @param {Event} event * @param {Number} questionId * @param {String} message - Plain text message to display */ onValidationMessageShown: function(event, questionId, message) { }, /** * Runs when the engine instructs to remove a validation message * @param {Event} event * @param {Number} questionId * @param {String} message - Plain text message to display */ onValidationMessageCleared: function(event, questionId) { } } // Now we register the custom question type to the configurator engine configurator.registerQuestionType(customQuestionType); });
Compare with built-in question type JS Objects which are located in [applicaton assets folder]/javascript/questions.js.
A view class
Add a view class in the location [customization_folder]/views/question_customtype/view.html.php and use the class name ConfigboxViewQuestion_Customtype.
class ConfigboxViewQuestion_Customtype extends ConfigboxViewQuestion { function prepareTemplateVars() { parent:prepareTemplateVars(); } }
You can see class members in ConfigboxViewQuestion, these will all be available to you in the template. The parent class' prepareTemplateVars method sets all template variables, in the override you can add data.
A view template
Add a view template in the location [customization_folder]/views/question_customtype/tmpl/default.php
Every question template needs to have the <div> wrapper below.
<?php defined('CB_VALID_ENTRY') or die(); /** @var $this ConfigboxViewQuestion_Customtype */ ?> <div id="<?php echo hsc($this->questionCssId);?>" class="<?php echo hsc($this->questionCssClasses);?>" <?php echo $this->questionDataAttributes;?>> </div>
Within the template and this wrapper, you add HTML and question data as needed. You can compare the template with the ones of the built-in question types in [application_dir]/views/question_*
CSS Styling
Use the custom.css file for any styling you need to apply. It’s recommended to use this parent selector.
.question.type-customtype .anything { }