eRaay - Survey Programmers Guide
Introduction
Welcome to eRaay!
This document provides comprehensive programming instructions to help you effectively use eRaay as your survey.
Need for a Programmer’s Guide
Usually, the eRaay survey platform provides all the features to design your survey within the platform itself. However, a survey can be of any complexity, which might need customizations outside the boundary of the eRaay platform. In such cases, eRaay’s functionality can be extended using additional programming.
Key Technologies
In order to extend this document, you need to have sound knowledge on the following:
- Internet Information Services (IIS)
- Visual Studio Code
- jQuery
- HTML/CSS
eRaay Survey Programming Editor
At the top of the editor, four buttons are displayed to help manage and test your survey logic:
-
File Selector (Dropdown): Allows you to choose between available JavaScript files.
custom.js– Default selected. This file contains the main custom logic for the survey, including step-by-step functions and documentation.config.js– Used for optional configuration or supporting logic.
- Compile & Save: Compiles the selected file to check for errors. If no errors are found, the code is saved to your preview version. If errors exist, they are displayed in a bottom message box for correction.
- Publish: After successful testing, click to publish your preview code to production. Important: Ensure there are no errors before publishing.
- Live Preview: Shows how your logic behaves in real-time. This helps verify your changes before going live.
Tip: At the top right of the editor, you'll see two timestamps:
- Last Modified: Date and time of your most recent saved preview code.
- Last Published: Date and time when code was last deployed to production.
Compare these timestamps to know whether your latest changes have been published.
The custom.js file contains the main JavaScript logic that powers dynamic survey behaviors. It includes structured, step-by-step functions and logic that you can customize for your survey requirements.
Below is the list of predefined functions available inside custom.js:
1. Init()
Description: This function is automatically called when the survey page loads. You can place initialization logic here such as setting up variables, hiding elements, or triggering startup events.
2. AfterPiping(questionNo)
Description: Called after piping (auto-filling options based on previous responses) is applied.
Use Cases:
- Count the number of piped options.
- Update elements like ranking dropdowns based on piped options.
questionNo(number): The specific question number being handled.
3. RandomizeQuestion()
Description: Randomizes a sequence of questions within a specified range.
Important: Questions must be consecutive with no branching logic in between.
Example: RandomizeQuestionSet("Q2", "Q10");
4. ManagePrevBtnClick()
Description: (If implemented) This function is triggered when the "Previous" button is clicked. You can place any specific logic or data rollback behavior here.
5. ManageNextBtnClick(questionNo, result)
Description: Triggered when the "Next" button is clicked. Allows validations or navigation control.
Use Cases:
- Validate input (e.g., ranking order with
validateRankSequence()) - Navigate to specific questions or end the survey using return commands
questionNo(number): The current question numberresult: The current answer values (e.g., "1,2,3")
false– Prevents proceeding (used in case of failed validations)GOTO|0– Jump to the end of the surveyGOTOQUESTIONNUMBER|Q1– Jump to a specific question
6. PopulateSurveyInfo()
Description: (Optional implementation) Can be used to auto-fill survey-level data or meta information into the survey.
7. PresetValues(objThisInfo)
Description: Preselects values in questions based on external or pre-uploaded data.
Use Cases: Useful in pre-filling user profile fields like name, mobile number, location, etc.
Example: SetDefaultValue("step3", objThisInfo.var7);
Parameters:
objThisInfo: Contains propertiesvar1tovar20
8. ApplyCustomQuota(result, queNumber)
Description: This function is called before the Next button proceeds, to validate quota limits based on custom logic.
Use Cases:
- Check combinations of answers against predefined quota restrictions
result: Answer valuesqueNumber: The current question number
Predefined functions
eRaay provides predefined functions to help you implement custom functionality easily.
Ranking (Drag and Drop) using Matrix Textbox
To implement a ranking drag-and-drop feature for a matrix of textboxes, here’s a guide on setting up the enableDragDropRanking function. This function enables users to rank items by dragging and dropping them within a specified question element, based on the given question number and maximum ranking.
-
To enable drag-and-drop ranking functionality, call
enableDragDropRankinginside an init function, passing in the question number and the maximum ranking limit. - If the maximum rank is not reached, a default rank will be automatically applied to all items.
Example:
enableDragDropRanking("Q5", 3);
Ranking (Dropdown) using Matrix Dropdown
To implement a document ranking feature using dropdowns with conditional piping, follow these steps. This includes validation for proper rank sequences and logic to control the Next button behavior.
-
AfterPiping Function: This detects changes from piped questions and updates the ranking dropdown dynamically.
if (queNumber == 'Q2') { manageRankDisplay(queNumber); } - validateRankSequence Function: This ensures that the selected ranks follow a valid sequence with no duplicates.
-
ManageNextBtnClick Function: On "Next" button click, call
validateRankSequenceto validate ranking before continuing.switch (QuestionNo) { case "Q2": if (!validateRankSequence(QuestionNo)) { return false; } break; }
Ranking (Textbox) using Matrix Textbox
To implement a document ranking feature using a textbox with conditional piping and managing button clicks, follow these steps:
-
manageRankDisplay Function: This function manages multiple input fields for ranking and applies validation logic based on the rank values. It dynamically sets the maximum rank (
max) and adds theDKCSrank class if necessary. -
validateRankSequence Function: This function checks if the entered rankings are in a valid sequence.
Example:switch (QuestionNo) { case "Q1": manageRankDisplay("Q4", 2, true); break; }
Ranking (Click) using Matrix Textbox
The clickRankHandler function facilitates a ranking system within a matrix textbox layout, allowing users to rank rows dynamically using a clickable interface.
Parameters:
questionNumber (string): Identifier for the question table, used to dynamically target the table and associated elements.maxRank (number): Maximum number of ranks allowed for the question; this limit is enforced during ranking.
Usage:
clickRankHandler("Q26", 3);
Randomize Matrix Row
The randomizeMatrixRows function is designed to randomize rows within a specified range for a matrix-type question in a survey. This enhances question variability and can prevent response biases by displaying options in a different order each time.
Call randomizeMatrixRows inside the ManageNextBtnClick function to apply row randomization before navigating to the next question.
Parameters:
questionNumber (string): The unique identifier for the matrix question.minRow (number): The minimum row index to begin randomizing (1-based index).maxRow (number): The maximum row index to include in randomization.
Example:
switch (QuestionNo) {
case "Q1":
randomizeMatrixRows("Q2", 2, 5);
break;
}
Randomize Option
The randomizeOptionsPreserveOrder function randomizes the display order of options within a specific range for a given question. Options outside the specified range, or specific options to be excluded, are preserved in their original order. This is useful in scenarios where only part of a question’s options need to be randomized to add variation.
Call randomizeOptionsPreserveOrder inside the ManageNextBtnClick function to apply option randomization before navigating to the next question.
Parameters:
questionNumber (string): The identifier for the question whose options are to be randomized.minOption (number): The minimum index of options to include in randomization (1-based index).maxOption (number): The maximum index of options to include in randomization.
Example:
switch (QuestionNo) {
case "Q1":
randomizeOptionsPreserveOrder("Q2", 2, 5);
break;
}
Randomize Question
The RandomizeQuestionSet function is used to randomize the order of survey questions between a specified starting and ending question. This ensures that questions within the defined range appear in a different order each time the survey is loaded, while maintaining logical flow and navigation integrity.
Call RandomizeQuestionSet inside your RandomizeQuestion function to apply the randomization before the survey is rendered.
Parameters:
startQuestionNo (string): The unique identifier of the first question in the range to be randomized.endQuestionNo (string): The unique identifier of the last question in the range to be randomized.
Example:
RandomizeQuestionSet("Q2", "Q10");
Sum Column Value and Set in Last Row using Matrix Textbox
The calculateColumnTotal function is used in matrix-style questions to automatically compute the sum of values in a specific column and display the result in the last row of that column. The input field in the last row is disabled to prevent manual edits and ensure data consistency.
Call the function calculateColumnTotal inside your initialization function to enable real-time calculation and display of totals.
Parameters:
questionNo (string): The unique identifier for the matrix question (e.g., "1", "Q2"). Used to select the correct table (e.g.,#tbl1,#tblQ2).columnNumber (number): The column index to calculate the total for. This corresponds to thecolnameattribute in the table’s input cells.
Example:
calculateColumnTotal("Q13", 1);
Validate Column Sum Equals 100
The validateColumnSumEquals100 function ensures that the sum of input values in specific columns of a matrix-style table equals exactly 100. If any specified column’s total is not 100, an error message is displayed and the function returns false, preventing progression.
Call validateColumnSumEquals100 inside the ManageNextBtnClick function to enforce validation before moving to the next question.
Parameters:
questionNumber (string): Unique identifier for the matrix question (e.g., "1", "Q2"). Used to locate the corresponding table (e.g.,#tbl1or#tblQ2).colNames (string): Comma-separated list of column names (e.g., "1,2,3") to validate. These match thecolnameattribute in table cells.
Example:
switch (QuestionNo) {
case "Q13":
if (!validateColumnSumEquals100("Q13", "1")) {
return;
}
break;
}
Get an Answer by Step ID
The getAnswerByStepId function retrieves the value of the answer attribute from a specific <div> element identified by its stepId. This is particularly useful for dynamically accessing responses in a multi-step form or survey where each step is encapsulated within a .step-pane div.
Parameters:
stepId (string): The ID of thediv.step-paneelement from which the answer attribute value should be fetched.
Return Value:
Returns the value of the answer attribute from the specified div.step-pane element.
Example:
getAnswerByStepId("step1");
Get an Answer by Question ID
The getAnswerByQueId function retrieves the value of the answer attribute from a <div> element identified by its queid. This function is useful for accessing answer values dynamically in form or survey applications where each question is uniquely referenced by a question ID.
Parameters:
queid (string): Thequeidattribute of thediv.step-paneelement from which the answer needs to be fetched.
Return Value:
Returns the value of the answer attribute from the specified div.step-pane element.
Example:
getAnswerByQueId("47382");
Get an Answer by Question Number
The getAnswerByQueNo function retrieves the value of the answer attribute from a <div> element identified by its qno. This is particularly useful in form or survey applications where responses are tracked and referenced using question numbers.
Parameters:
qno (string): Theqnoattribute of thediv.step-paneelement from which the answer value should be retrieved.
Return Value:
Returns the value of the answer attribute from the targeted div.step-pane element.
Example:
getAnswerByQueNo("Q1");
Get Question Number by Question ID
The getQesNoByQueId function retrieves the value of the qno attribute from a <div> element identified by its queid. This is especially useful when mapping unique question IDs to their respective question numbers in dynamic survey flows.
Parameters:
queid (String | Number): Thequeidattribute of thediv.step-paneelement whoseqnoneeds to be retrieved. If passed as a string, it is automatically converted to a number.
Return Value:
Returns the value of the qno attribute from the targeted div.step-pane element.
Example:
getQesNoByQueId("47382");
Get Step ID by Question Number
The getStepId function retrieves the id attribute of a <div class="step-pane"> element identified by its qno (question number). This is particularly useful for managing survey step transitions or navigating to a specific question.
Parameters:
questionNo (String): Theqnoattribute of thediv.step-paneelement from which theidvalue is to be retrieved.
Return Value:
Returns the id of the matched div.step-pane element.
Example:
getStepId("Q1");
Get Display Sequence Number by Target ID
The getDsqNo function retrieves the sequence number (dsq) from a div.step-pane element, identified by the question number (qno). The qno is obtained based on the provided tgtId using the getQesNoByTgtId function. This function is useful for dynamically fetching a display sequence number associated with a specific question in a survey or form.
Parameters:
tgtId (String | Number): The target ID used to look up the corresponding question number (qno) and retrieve thedsqattribute value.
Return Value:
Returns the value of the dsq attribute from the div.step-pane element with the matching qno.
Example:
getDsqNo('47382');
Get Timer Value by Target ID
The getdtimer function retrieves the value of the dtimer attribute from a div.step-pane element, identified by the question number (qno), which is determined based on the provided tgtId. This function is useful for dynamically fetching the timer value (dtimer) for a specific question within a survey or form.
Parameters:
tgtId (String | Number): The target ID used to find the corresponding question number (qno) and retrieve thedtimerattribute value. This ID is passed to thegetQesNoByTgtIdfunction to locate the relevantqno.
Return Value:
The value of the dtimer attribute from the div.step-pane element matching the given qno.
Example:
getdtimer('47382');
Get Answer Type by Question Number
The getAnswerType function retrieves the answertype attribute value from a specific element associated with a given question number (qno). The function first attempts to find the answertype from a table-custom element (typically used for matrix-style questions) and, if not found, falls back to searching within an elem-group element (commonly for text box-style questions). This function is useful for dynamically determining the answer type of a question in a form or survey application.
Parameters:
questionNo (String | Number): The question number (qno) used to locate the specific question element in the DOM and retrieve theanswertypeattribute.
Return Value:
The value of the answertype attribute from the identified question element.
Example:
getAnswerType('Q1');
Get Table ID by Question Number
The getTableId function retrieves the id attribute of a table element associated with a specific question number (qno). This function is useful for dynamically fetching the table ID of matrix-style questions or any table-based elements within a form or survey application.
Parameters:
questionNo (String | Number): The question number (qno) used to locate the specific question element in the DOM and retrieve theidattribute of the associated table.
Return Value:
The id attribute of the table element associated with the specified question number.
Example:
getTableId('Q1');
Get Question ID by Question Number
The getQuesId function retrieves the queid attribute from the question element associated with a specific question number (qno). This function is useful for dynamically fetching the question ID in a form or survey application where questions are identified by question numbers.
Parameters:
questionNo (String | Number): The question number (qno) used to locate the specific question element in the DOM and retrieve thequeidattribute.
Return Value:
The queid attribute value of the question element associated with the specified question number.
Example:
getQuesId('Q1');
Get Question ID by Step ID
The GetQuestionIdByStepId function retrieves the queid attribute of a specific question element by using the provided StepId. This function is useful when working with dynamic forms or surveys, especially when you need to access the question ID for a particular step in the process.
Parameters:
StepId (String): The ID of the step (typically adivelement) for which thequeidattribute needs to be retrieved.
Return Value:
The queid attribute value of the element with the specified StepId.
Example:
GetQuestionIdByStepId('step1');
Display Error Message with Bootstrap Alert
The errorMessage function displays an error message using a Bootstrap-styled alert. This function can be used to show error notifications or validation messages in a user-friendly manner, utilizing Bootstrap's alert components.
Parameters:
msg (String): The error message that will be displayed in the alert.
Return Value:
This function does not return any value. It simply triggers the display of an error message using a Bootstrap alert.
Example:
errorMessage('this is test message');
Get Selected Options by Question Number
The getSelectedOptionsByQuestion function retrieves the selected radio or checkbox options for a specific question identified by its question number (questionNumber). It returns the values and corresponding texts of the selected options within the question. This function is useful for collecting user input in forms or surveys.
Parameters:
questionNumber (String | Number): The question number (data-qno attribute) used to locate the question container and find the selected options.
Return Value:
Type: Object
Description: The function returns an object with the following structure:
selected(Boolean): true if one or more options are selected, false if none.values(Array): Values of the selected options.texts(Array): Text labels corresponding to each selected option, fetched from the closest label with the class.clsOptionText.
Example:
getSelectedOptionsByQuestion('Q1')
Check if Input is Numeric on Keypress
The IsNumeric function is typically used in the onkeypress event handler to ensure that the user can only enter numeric characters (digits 0-9) in a specific input field. This helps restrict input to numeric values by preventing any non-numeric characters from being entered.
Example Usage:
<input type="text" onkeypress="return IsNumeric(event);" />
Check if Input is Alphabetical on Keypress
The IsAlpha function is commonly used in the onkeypress event handler to ensure that only alphabetic characters (letters) are entered in a specific input field. This restricts input to letters (both uppercase and lowercase), preventing non-alphabetical characters from being typed.
Example Usage:
<input type="text" onkeypress="return IsAlpha(event);" />
Get Matrix Row Values
The getMatrixRowValues function retrieves specific row values from a matrix answer based on the question number and row number. This function supports multiple matrix types, including textboxes, dropdowns, single answer (radio buttons), and multiple answer (checkboxes), dynamically parsing and filtering the data accordingly.
Parameters
result(String): The answer data. If empty, the function fetches the answer usinggetAnswerByQueNo.questionNo(Number): The question number associated with the matrix.rowNumber(Number): The row number for which values are required.
Return Value
Type: Array
Returns an array of values or key-value pairs depending on the matrix type:
- For textboxes and dropdowns: Key-value pairs of column numbers and values.
- For single answer matrices: A list of selected values.
- For multiple answer matrices: An array of selected values per row.
Example
getMatrixRowValues("", 'Q2', 2)
Get Matrix Column Values
The getMatrixColumnValues function extracts specific column values from a matrix answer based on the question number and column number. It supports various matrix types such as textboxes, dropdowns, single answer (radio buttons), and multiple answer (checkboxes), parsing and filtering the answer data accordingly.
Parameters
result(String): The answer data. If empty, the function fetches the answer usinggetAnswerByQueNo.questionNo(Number): The question number associated with the matrix.columnNumber(Number): The column number for which values are required.
Return Value
Type: Array
Returns an array of values or key-value pairs based on the matrix type:
- For textboxes and dropdowns: Key-value pairs of row numbers and values.
- For single answer matrices: A list of selected rows for the column.
- For multiple answer matrices: An array of selected rows for the column.
Example
getMatrixColumnValues("", 'Q2', 2)
Retrieve Matrix Cell Value
The getMatrixCellValue function extracts the value from a specific cell in a matrix-style question's response based on the provided row and column numbers. This is useful for accessing precise data points in matrix questions stored in a structured format.
Parameters
result(String): The answer string containing the matrix values. If empty, the function fetches the answer dynamically.questionNo(Number): The question number to which the matrix belongs.rowNumber(Number): The row number of the cell to retrieve.columnNumber(Number): The column number of the cell to retrieve.
Return Value
String: The value of the matrix cell at the specified row and column.
Example
getMatrixCellValue("", 'Q2', 2, 2)
Validate Matrix Input Rows
The validateMatrixInputRows function validates the input data for all visible rows within a matrix-style question. It verifies that each visible row contains at least one valid input, marks invalid rows with a specific CSS class, and returns a validation result.
Parameters
questionNo(Number): The question number identifying the matrix question. This is used to locate the matrix table in the DOM.
Return Value
Boolean: Returns true if all visible rows are valid; false if any visible row is invalid.
Example
if (!validateMatrixInputRows('Q13')) {
return false;
}
Enable/Disable Column
The enableDisableColumn function enables or disables specified columns in a matrix-style table associated with a given question number. When disabling, the function clears any input values in the targeted columns and applies styles to visually indicate the disabled state.
Parameters
questionNo(String): The question number identifying the matrix table (used to locate the table by its ID).colNumbers(String): Comma-separated column numbers to enable or disable (e.g., "1,3,5").isDisable(Boolean): Flag to disable (true) or enable (false) the specified columns.
Example
enableDisableColumn('Q13', '1,3', true); // Disables columns 1 and 3 in matrix question Q13
enableDisableColumn('Q13', '2', false); // Enables column 2 in matrix question Q13
Enable/Disable Row
The enableDisableRow function enables or disables specified rows in a matrix-style question’s table. It affects all input elements (such as input, select) inside the targeted rows, making them interactive or read-only according to the flag.
Parameters
questionNo(String): The question number to identify the matrix table by its ID.rowNumbers(String): Comma-separated list of row numbers to enable or disable (e.g., "1,3,5").isDisable(Boolean): Set totrueto disable the rows, orfalseto enable them.
Example
enableDisableRow('Q13', '2,4', true); // Disables rows 2 and 4 in matrix question Q13
enableDisableRow('Q13', '1', false); // Enables row 1 in matrix question Q13
Enable/Disable Cell
The enableDisableCell function enables or disables input elements in specific cells of a matrix-style question’s table. It targets the cells by their row and column numbers, allowing fine-grained control over user interaction within the matrix.
Parameters
questionNo(String): The question number to identify the matrix table by its ID.rowNumber(String): The row number where the target cells reside.colNumbers(String): Comma-separated list of column numbers specifying which cells to enable or disable (e.g., "1,3,5").isDisable(Boolean): Set totrueto disable the specified cells, orfalseto enable them.
Example
enableDisableCell('Q14', 2, '3', true); // Disables the cell at row 2, column 3 of matrix Q14
enableDisableCell('Q14', 1, '1,4', false); // Enables cells at row 1, columns 1 and 4 in matrix Q14
Get Matrix Input Values
The getAllMatrixInputValues function retrieves values from a matrix table
based on the provided question number, and optionally filters by row and/or column. It supports input fields for
answertype 10, 11, and 12 (using <input class="dataval">),
and dropdowns for answertype 21 (using <select>).
Parameters
-
questionNo(String): Required. The question number used to locate the matrix table (e.g.,tblQ13). -
rowNo(String, optional): Row identifier to filter results by a specific row. -
colNo(String, optional): Column identifier to filter results by a specific column.
Return Value
The return type depends on the parameters:
- If only questionNo is passed: returns an array of objects for all rows and columns.
- If questionNo + rowNo or colNo: returns an array of matching cells.
- If questionNo + rowNo + colNo: returns a single value (string) for that cell.
-
Returns an empty array if
answertypeis not one of 10, 11, 12, or 21.
Examples
// Get all values from Q14
const allValues = getAllMatrixInputValues('Q14');
// [
// { rowname: "1", colname: "1", value: "2" },
// { rowname: "2", colname: "1", value: "4" }
// ]
// Get values from row "2" of Q14
const rowValues = getAllMatrixInputValues('Q14', '2');
// [
// { rowname: "2", colname: "1", value: "4" }
// ]
// Get values from column "1" of Q14
const colValues = getAllMatrixInputValues('Q14', null, '1');
// [
// { rowname: "1", colname: "1", value: "2" },
// { rowname: "2", colname: "1", value: "4" }
// ]
// Get value from row "3", column "1" of Q14
const cellValue = getAllMatrixInputValues('Q14', '3', '1');
// "Op3"
Get Selected Image Title
The getSelectedImageTitle function retrieves the title attribute of the image linked to the selected radio button for a specified question. It helps capture the user's image selection in surveys or forms.
Parameters
questionNumber(String): The question number to identify the related set of radio buttons.
Return Value
- Type: String
- Description: Returns the title of the selected image. Returns
"Na"if no radio button is selected, or"No title found"if the selected image has no title attribute.
Example
const title = getSelectedImageTitle('Q10');
console.log(title); // Outputs the selected image title or fallback message
Dynamic Matrix Row Visibility Control
The manipulateMatrixRowVisibility function controls the visibility of rows in a matrix-style table based on the answer given for another question. It compares answer types of two questions (QuestionNo1 and questionNo2) and shows or hides rows in the second matrix accordingly.
Parameters
result(String or undefined): The answer value fromQuestionNo1. If empty, the function may fetch this value internally.QuestionNo1(String): The question number of the first question from which the answer value is taken.questionNo2(String): The question number of the second matrix where row visibility will be manipulated.
Return Value
- Type: Boolean (optional)
- Description: Returns
falseif the answer types do not satisfy the conditions; otherwise, no explicit return (orundefined).
Example
manipulateMatrixRowVisibility('', 'Q12', 'Q13');
Numeric Validation for Matrix Columns
The initMatrixColNumericValidation function enforces numeric validation on specified columns of a matrix table. It ensures inputs are numeric and within a specified range (minimum to maximum). If users input non-numeric or out-of-range values, an error message is displayed. The validation uses onkeypress to restrict characters to numeric ones and dynamically validates the input on change.
Parameters
questionNo(String): Identifier for the matrix question.columns(String): Comma-separated list of column numbers where validation applies.min(Number): Minimum allowed input value.max(Number): Maximum allowed input value.
Return Value
- None: The function modifies input fields to apply validation but does not return a value.
Example
initMatrixColNumericValidation('Q13', '1', 1, 5);
Numeric Listener for Matrix Cells
The initMatrixCellNumericListener function attaches numeric validation listeners to specified cells within a matrix-style table. It restricts user input to numeric characters only by setting onkeypress handlers that call an IsNumeric function for validation.
Parameters
questionNo(String): Identifier for the matrix question.rowNames(String): Comma-separated list of row names where the numeric listener applies.columns(String): Comma-separated list of column names where the numeric listener applies.
Return Value
- None: The function modifies the input fields in the specified cells to allow numeric input only.
Example
initMatrixCellNumericListener('Q13', '2', '1');
Alpha Listener for Matrix Columns
The initMatrixColAlphaListener function adds an alphabetical validation listener to specified columns in a matrix-style table. It ensures that only alphabetic characters (letters) can be entered in the input fields of those columns by attaching an onkeypress event handler that calls the IsAlpha function.
Parameters
questionNo(String): The identifier for the matrix question.columns(String): Comma-separated list of column numbers where the alpha listener should be applied.
Return Value
- None: The function modifies input fields in the specified columns to accept only alphabetic input.
Example
initMatrixColAlphaListener('Q13', '2');
Phone Number Validation for Matrix Cells
The initMatrixCellTelephoneValidation function applies phone number validation to specific cells in a matrix-style table. It restricts input to numeric characters only, validates that the input matches a valid phone number format, and enforces a maximum length of 10 characters for the phone number field.
Parameters
questionNo(String): The identifier for the matrix question.rowNames(String): Comma-separated list of row names where phone validation should be applied.columns(String): Comma-separated list of column names where phone validation should be applied.
Return Value
- None: The function modifies the input fields in specified cells to enforce phone number validation.
Example
initMatrixCellTelephoneValidation('Q13', '2', '1');
Customization of Matrix Question Input Field
The customizeMatrixQuestion function allows customization of a specific column within a matrix-style question by inserting additional HTML elements after the corresponding input fields. It supports associating different input types such as dropdowns, checkboxes, radio buttons, and textboxes with the matrix input fields.
Parameters
questionNo(String): The identifier for the matrix question.column(String | Number): The column number or identifier where customization is applied.element(String): The HTML string of the element to insert after the input fields (e.g., dropdown, checkbox, radio button, textbox, etc.).
Return Value
- None: The function modifies the specified column by appending the given HTML element after the corresponding input fields.
Example
var dropdownHTML = '<select id="dropdownnnn" class="form-control">' +
'<option value="0">Select</option>' +
'<option value="1">Rank 1</option>' +
'<option value="2">Rank 2</option>' +
'<option value="3">Rank 3</option>' +
'<option value="4">Rank 4</option>' +
'<option value="5">Rank 5</option>' +
'<option value="6">Rank 6</option>' +
'<option value="7">Rank 7</option>' +
'<option value="8">Rank 8</option>' +
'<option value="9">Rank 9</option>' +
'</select>';
customizeMatrixQuestion("Q13", 1, dropdownHTML);
Customization of Matrix Question in Specific Cell
- Cell Styling: Customize specific cell appearance.
- Logic: Apply cell-specific validation.
The customizeMatrixQuestioninCell function allows for the customization of a specific cell within a matrix-style question by inserting an HTML element after the input field in the specified row and column. This function targets a single cell, unlike customizeMatrixQuestion, which applies changes to an entire column.
Parameters
questionNo(String): The identifier for the matrix question.rowname(String | Number): The row name or identifier where customization will be applied.column(String | Number): The column number or identifier where customization will be applied.element(String): The HTML element to insert after the matrix input field (e.g., dropdown, checkbox, radio button, textbox, etc.).
Return Value
- None: The function modifies the specified cell by appending the given HTML element after the corresponding input field within the row and column.
Example
var dropdownHTML = '<select id="dropdownnnn" class="form-control">' +
'<option value="0">Select</option>' +
'<option value="1">Rank 1</option>' +
'<option value="2">Rank 2</option>' +
'<option value="3">Rank 3</option>' +
'<option value="4">Rank 4</option>' +
'<option value="5">Rank 5</option>' +
'<option value="6">Rank 6</option>' +
'<option value="7">Rank 7</option>' +
'<option value="8">Rank 8</option>' +
'<option value="9">Rank 9</option>' +
'</select>';
customizeMatrixQuestioninCell("Q13", 2, 1, dropdownHTML);
Update Checkbox Options to "NOTA" (None of the Above)
The updateOptionToNota function updates the styling and behavior of specific checkbox options for a given question. It ensures that the specified checkboxes act as "None of the Above" (NOTA) options by applying the correct class, removing any previous change handlers, and binding new behavior to make them mutually exclusive with other checkboxes.
Parameters
questionNumber(Number | String): The identifier for the question (e.g., "Q5").optionValues(String | Array): A comma-separated string (e.g., "1,2,3") or an array of option values representing the NOTA checkboxes.
Return Value
- None: This function does not return a value. It updates the DOM elements and logs errors if invalid input is given.
Function Behavior
- Updates the parent container’s CSS class for the specified checkbox options.
- Removes existing
onchangeattributes from the checkboxes. - Attaches a new
onchangeevent handler:UncheckAllOtherCheckbox(this). - Adds the class
Notato the checkbox inputs for identification.
Example
// Set option 4 of question Q5 as a NOTA checkbox
updateOptionToNota("Q5", "4");
Validate Checkbox Mutual Exclusivity
The validateCheckboxMutualExclusivity function enforces mutual exclusivity rules within a matrix question's column. If a special checkbox (like "None of the Above") is selected, all other checkboxes in that column are automatically unchecked. Conversely, selecting any other checkbox will uncheck the special one.
Parameters
questionNumber(Number | String): The unique identifier for the matrix question (e.g., "I" or "Q7").columnNumber(Number): The column index where the checkboxes are located.specialValue(Number, optional): The row value considered special (e.g., 999 for NOTA). Defaults to999.
Return Value
- void: This function does not return a value. It adjusts the checked state of checkboxes based on selection logic.
Function Behavior
- Attaches a
changeevent listener to each checkbox in the specified question and column. - If the special checkbox (like NOTA) is selected, it unchecks all others in the column.
- If any other checkbox is selected, it unchecks the special checkbox.
- Useful for ensuring mutual exclusivity in matrix-style checkbox questions.
Example
// Enforce mutual exclusivity for question I, column 1, using 999 as the NOTA row value
validateCheckboxMutualExclusivity('I', 1);
Validate Checkbox Selection Count
The validateCheckboxSelectionCount function ensures that users select at least a specified number of checkboxes in a given column of a matrix-style question. It optionally accounts for a special checkbox (e.g., "None of the Above") and skips validation if that is selected.
Parameters
questionNumber(Number | String): The unique identifier for the question (e.g., "I" or "Q4").columnNumber(Number): The column number in the matrix where validation should apply.minCheckBox(Number): Minimum number of checkboxes that must be selected to pass validation.specialValue(Number, optional): A special row value (like 999 for NOTA) that bypasses selection count when checked. Defaults to999.
Return Value
- Boolean: Returns
trueif the selection meets the minimum required count, otherwisefalse.
Function Behavior
- Counts the number of checked checkboxes in the specified column.
- If the special checkbox is not selected, enforces that the minimum number of checkboxes are checked.
- Displays an error message if the requirement is not met.
Example
// Validate that exactly 1 checkbox is selected in question 'I', column 4
switch (QuestionNo) {
case "Q4":
var isValidCol4 = validateCheckboxSelectionCount('I', 4, 1);
if (!isValidCol4) {
return false;
}
break;
}
Validate and Map Code Inputs Based on External Data
The validateCodeMapping function dynamically validates an entered code against an external JSON dataset and populates related fields if a valid match is found. This is useful for code-to-name mappings, such as mapping institute codes to names and cities.
Parameters
questionNo(Number | String): Identifier for the question (e.g., "Q5x1a").identifier(String): Key name to match the user input against the JSON data.jsonFileUrl(String): URL of the JSON file to fetch the data from.-
colMapping(Object): Column mappings to control input and display fields.inputCol: Column number where the input code is entered.nameCol: Column number to display the matched name.cityCol: Column number to display the matched city.
overlaySelector(String, optional): CSS selector for the loading spinner. Defaults to".overlay-spinner".
Return Value
- void: The function does not return any value. It performs DOM manipulations and AJAX operations.
Function Behavior
- Listens for input changes in the designated column of the question.
- Fetches data from the given JSON file using AJAX.
-
If a matching entry is found:
- Populates the related fields with name and city.
- Disables editing of those fields to prevent manual changes.
- If no match is found, displays an error and clears dependent fields.
Example
const colMapping = {
inputCol: 1, // Column with code input
nameCol: 2, // Column for name output
cityCol: 3 // Column for city output
};
validateCodeMapping("Q5x1a", "InstituteIdentifier", "abcd.json", colMapping);
Validate Sequential Ranking
The validateSequentialRanking function ensures that the ranking values in a given column of a question follow a strict ascending sequence starting from 1 (e.g., 1, 2, 3, ...). It is typically used in ranking-based surveys or forms to prevent skipped or duplicate ranks.
Parameters
questionNumber(Number | String): The unique identifier for the question (e.g., "Q4x1a").columnNumber(Number): The column number that contains the ranking inputs.
Return Value
- true: If all rankings are valid and sequential starting from 1.
- false: If there are gaps, duplicates, or out-of-order values.
Function Behavior
- Collects all numeric inputs in the specified column of the given question.
- Sorts and compares the values to ensure they form a perfect sequence: 1, 2, 3, ..., N.
- Displays an error message if the values are not in sequential order or contain invalid entries.
Example
switch (QuestionNo) {
case "Q4x1a":
if (!validateSequentialRanking("Q4x1a", 2)) {
return false;
}
break;
}
Validate Code Sequence
The validateCodeSequence function ensures that all values in a specified column are unique and non-zero. It is commonly used in tables where users enter ranking codes, positions, or unique identifiers to prevent duplication and invalid entries.
Parameters
questionNumber(Number | String): The unique identifier for the question (e.g., "Q4x1a").columnNumber(Number): The column number to validate within the question's table.
Return Value
- true: If all values in the column are unique and non-zero.
- false: If any duplicate or zero value is found.
Function Behavior
- Scans all inputs in the specified column under the given question's table.
- Checks for zero values (e.g., 0 or empty) and duplicates.
- Displays an appropriate error message if invalid entries are found.
Example
switch (QuestionNo) {
case "Q4x1a":
if (!validateCodeSequence("Q4x1a", 2)) {
return false;
}
break;
}
Validate At Least One Value Per Row
The validateAtLeastOneValuePerRow function checks every visible row within the question's table to confirm that at least one text input has a value. If any row is completely empty, an alert is shown, and the first empty input of that row is focused for user correction.
Parameters
questionNo(Number | String): The identifier for the question, used to locate the relevant table (e.g., "Q2").
Return Value
- boolean: Returns
trueif all visible rows have at least one filled input; otherwise,false.
Usage Example
validateAtLeastOneValuePerRow("Q2");
Calculate Total for All Columns
The calculateTotalForAllColumns function calculates the sum of all numeric inputs across every column in the table associated with the given question number. This operation applies only when the answer type is "12", ensuring context-specific calculation.
Parameters
questionNo(Number | String): The identifier for the question, used to locate the table by its ID (e.g.,"Q1"or1).
Return Value
- number: Returns the total sum of all numeric input values within the table.
Usage Example
const total = calculateTotalForAllColumns("Q1");
console.log("Total Sum:", total);
Get Rows with Values
The getRowsWithValues function parses a data string and extracts unique row numbers where at least one column has a non-empty value. It is useful for determining which rows should be considered during validation or data submission.
Parameters
-
dataString(string): A pipe-separated string formatted as"row:column-value|...".
Example:"1:2-10|2:3-15|3:1-"
Return Value
Array<string>: An array of unique row numbers (as strings) that have at least one non-empty value.
Usage Example
const result = "1:2-10|2:3-15|3:1-";
const filledRows = getRowsWithValues(result);
console.log(filledRows); // Output: ["1", "2"]
Setup: Multi-Select Custom Grid with “Other (Specify)”
This setup enables dynamic control over a custom multi-select grid where a textbox (e.g., "Other (Specify)") is enabled only when a specific checkbox is selected. It involves two key steps:
-
enableDisableColumn(questionNumber, colname, true)
Disables all textboxes in the specified column initially (recommended during page load). -
handleCustomGridMultiSelectWithOther(questionNumber, othersOptionValue, colname)
Adds logic to conditionally re-enable the textbox when the "Other" checkbox is selected.
Usage Scenario
enableDisableColumn('Q1', '2', true);
handleCustomGridMultiSelectWithOther('Q1', '12', '2');
Parameters
questionNumber(string): The ID suffix used to target the grid table (e.g.,#tblQ1).othersOptionValue(string): The value of the checkbox option representing "Other (Specify)".colname(string): The column number or name where the corresponding textbox exists (e.g.,colname="2").
Function Behavior
- Listens to changes on checkboxes with class
.form-check-input.optioninside#tbl{questionNumber}. -
If the "Other" checkbox (based on
othersOptionValue) is checked:- Enables the corresponding textbox (input[type="text"][colname=X])
- Clears its value
- Sets focus
-
If unchecked:
- Disables the textbox
- Sets its value to
"NA"
-
Also handles
.select-allcheckboxes within the same row:- Checks or unchecks all checkboxes in that row
- Automatically toggles the "Other" textbox based on its inclusion
Setup: Custom Grid Dropdown with “Other (Specify)”
This function enables or disables a textbox (e.g., "Other (Specify)") inside a custom grid row based on the selected dropdown value. It's designed for grid tables where each row includes a <select> dropdown and an accompanying "Other" textbox.
Usage Scenario
enableDisableColumn('Q5', '3', true);
handleCustomGridDropdownWithOther('Q5', '99', '3');
First, enableDisableColumn disables all textboxes in column 3 on page load. Then handleCustomGridDropdownWithOther activates logic to re-enable the textbox only if the selected dropdown value matches the "Other" option (value 99).
Parameters
questionNumber(string): The ID suffix used to target the grid table (e.g.,#tblQ5).othersOptionValue(string): The value of the dropdown option representing "Other (Specify)".otherColname(string): The column number or name used in the textbox'scolnameattribute.
Function Behavior
- Listens for
changeevents on all<select>elements inside#tbl{questionNumber}. -
If the selected value matches
othersOptionValue:- Enables the corresponding textbox (based on
[colname=X]) - Clears its value
- Sets focus
- Enables the corresponding textbox (based on
-
If any other value is selected:
- Disables the textbox
- Sets its value to
"NA"
Conditionally Enable/Disable Questions
The conditionallyEnableDisableQuestions function dynamically enables or disables one or more target questions based on the selected value(s) from a source question. It's commonly used for conditional logic such as skip patterns in surveys or forms.
Usage Scenario
conditionallyEnableDisableQuestions('Q5', ['Q6', 'Q7'], ['3']);
In this example, if option 3 is selected in question Q5, questions Q6 and Q7 will be disabled (along with clearing any existing values).
Parameters
sourceQNo(string): The question number of the source input (e.g.,Q5).targetQNos(Array<string> | string): One or more target question numbers to enable/disable conditionally.disableOptionValues(Array<string>): The option values from the source question that trigger disabling of the target questions.
Function Behavior
- Listens for
changeevents on the source question inputs (radio buttons). - Checks if the selected value is in
disableOptionValues. -
If matched, for each target question:
- Clears selected values and disables input elements (checkboxes, radios, textboxes).
- Adds a
disabled-questionclass to the question container. - Sets
mandatoryattribute to'N'. -
If the target is a matrix question (
answertype="10"):- Disables all radio buttons and text inputs inside the table.
- Sets
allgridrowmandatoryattribute on the table to'N'or'Y'.
-
If not matched:
- Enables all target question inputs and restores required attributes.
- Removes
disabled-questionstyling.
Notes
- Works with both single and multiple target questions.
- Matrix grid questions should have
answertype="10"set on the container. - Use
getQuesIdinternally to handle any prefix stripping logic consistently.
Matrix Row-Based Conditional Question Toggle
The handleMatrixRowConditionalToggle function dynamically enables or disables a target question based on specific values selected in certain rows of a matrix-style radio button table.
Usage Scenario
handleMatrixRowConditionalToggle('Q8', [
{ row: '1', triggerValue: '2', targetQno: 'Q9' },
{ row: '3', triggerValue: '3', targetQno: 'Q10' }
]);
In this example, if row 1 of Q8 has a value 2 selected, Q9 is disabled. If row 3 has value 3 selected, Q10 is disabled.
Parameters
qno(string): The question number of the matrix table containing row-based radio buttons.-
conditionMap(Array of objects): Defines which rows/values should trigger disabling of specific questions.
Each condition object contains:row(string): The row identifier in the matrix (viarownameattribute).triggerValue(string): The radio value that triggers disabling.targetQno(string): The question number of the target to disable.
Function Behavior
- Listens to
changeevents on matrix-style radio buttons inside#tbl{qno}. - Checks whether a specified
rowhas atriggerValueselected. -
If matched:
- Disables and clears inputs in the corresponding
targetQno. - Sets
mandatory="N"and addsdisabled-questionclass. - Sets
allgridrowmandatory="N"if target is a matrix table.
- Disables and clears inputs in the corresponding
-
If not matched:
- Re-enables the inputs.
- Restores
mandatory="Y"and removesdisabled-questionclass.
Supported Input Types
- Matrix-style radio buttons (
answertype="10") - Standard radio, checkbox, and text inputs
Checkbox-Based Conditional Question Toggle
The handleCheckboxConditionalToggle function conditionally enables or disables a target question based on selected checkbox values from a source question. It supports various input types including checkboxes, radio buttons, text inputs, dropdowns, and textareas.
Usage Scenario
handleCheckboxConditionalToggle('Q12', [
{ triggerValue: '1', targetQno: 'Q13' },
{ triggerValue: '3', targetQno: 'Q14' }
]);
If checkbox with value 1 in Q12 is checked, Q13 will be enabled.
If checkbox with value 3 is checked, Q14 will be enabled.
If not selected, the corresponding target question(s) will be disabled and cleared.
Parameters
qno(string): The question number of the checkbox group. All checkboxes should use this class (e.g.,class="Q12").-
conditions(Array of objects): Array of condition rules. Each object must contain:triggerValue(string): The checkbox value that should enable the target.targetQno(string): The question number to enable/disable based on condition.
Function Behavior
- Listens to
changeevents on all checkboxes with class.{qno}. -
On checkbox state change:
- Collects all checked values.
-
If any condition’s
triggerValueis matched:- Enables the corresponding
targetQnoinputs. - Removes the
disabled-questionclass.
- Enables the corresponding
-
If not matched:
- Disables and clears all inputs in the target question (checkbox, radio, text, select, textarea, button).
- Adds the
disabled-questionclass. - For matrix tables, sets
allgridrowmandatory="N"when disabled,"Y"when enabled.
- Triggers an initial check on page load to set correct visibility based on pre-selected values.
Supported Target Inputs
input[type="checkbox"]input[type="radio"]input[type="text"]<select><textarea><button>
Trigger Radio Change by Value
The triggerRadioChangeByValue function programmatically triggers the change event on a specific radio button based on its value and question number. This is useful for initializing or simulating user interaction logic tied to radio input changes.
Usage Scenario
triggerRadioChangeByValue('Q6', '2');
This will trigger a change event on the radio button with class clsQ6 and value 2, allowing any attached logic (such as conditional question toggles) to execute.
Parameters
qno(string): The question number suffix used in the radio button class (e.g.,clsQ6).value(string): Thevalueattribute of the radio input that should be triggered.
Function Behavior
- Builds a selector using
input[type="radio"].cls{qno}[value="{value}"]. - Triggers the
changeevent on the matched radio input (if found). - If no matching radio button is found, logs a warning to the console.
Notes
- This does not check the radio button — it only triggers the
changeevent. Make sure the radio is also checked if needed. - Useful in scenarios where conditional logic depends on
changehandlers.
Trigger Checkbox Change by Values
The triggerCheckboxChangeByValues function programmatically triggers the change event for one or more checkboxes based on their values and associated question number. This is commonly used to activate conditional logic that depends on checkbox selections.
Usage Scenario
triggerCheckboxChangeByValues('Q12', '1,3,5');
This will trigger the change event for checkboxes with class Q12 and values 1, 3, and 5. Any logic listening to change on these checkboxes (e.g., conditional toggles) will be executed.
Parameters
qno(string): The question number used as a class name to identify checkboxes (e.g.,class="Q12").values(string): A comma-separated list of checkbox values to trigger (e.g.,"1,3,5").
Function Behavior
- Splits the
valuesstring into an array of individual values. -
Iterates through each value:
- Builds a selector
input[type="checkbox"].{qno}[value="{value}"]. - Triggers the
changeevent on the matched checkbox if found. - Logs to the console when triggered or if a matching checkbox is not found.
- Builds a selector
Notes
- This function does not check the checkboxes. If needed, use
.prop('checked', true)before triggering the event. - Primarily used to re-execute dependent logic without user interaction (e.g., on page load).
Trigger Matrix Radio Change by Row and Value
The triggerMatrixRadioValueChange function programmatically triggers the change event on a specific matrix-style radio button located in a specific row of a matrix table. This is useful for invoking conditional logic without manual user input.
Usage Scenario
triggerMatrixRadioValueChange('Q601_2', '1');
This will trigger the change event on the matrix radio button for question Q601, in row 2, with value 1. Any logic listening for that change will be executed.
Parameters
-
qnoWithRow(string): A combined string in the format"Q601_2"where:- Q601: Matrix question number
- 2: Row identifier (must match the
rownameattribute)
value(string): The value of the radio button to trigger in that row.
Function Behavior
- Parses the
qnoWithRowstring into a question number and row name. -
Constructs a selector targeting the matrix radio using:
#tbl{qno} input[type="radio"].matrix[rowname="{row}"][value="{value}"] -
If the radio input exists:
- Triggers its
changeevent.
- Triggers its
-
If not found:
- Logs a warning with the missing combination.
Notes
- This function does not select/check the radio button — it only fires the
changeevent. Use.prop('checked', true)if you want to simulate both selection and logic. - Make sure the
rownameattribute exists on the matrix radio inputs. - Useful for conditional question activation tied to matrix row selections.
Setup: Word Count Handler for Textareas
This setup enforces a minimum or maximum word count for textarea inputs in survey questions. It dynamically updates a message below the textarea indicating words remaining or exceeded.
-
setWordCountHandler(questionNumbers, minWords)
Assigns word count logic to the specified questions' textareas. Can accept a single question, multiple questions as separate arguments, or an array of question numbers.
Usage Scenario
setWordCountHandler(["Q6", "Q7"], 10);
Parameters
questionNumbers(array|string): One or more question IDs (e.g.,["Q6", "Q7"]or"Q6").minWords(number): Minimum word count required for the textarea.
Setup: Retrieve Input Value by Question Number
This function retrieves the value of the first input element (input, textarea, or select) inside a survey question container based on its question number (QNO). It supports specific answer types (e.g., text input or comment fields).
-
getInputValueByQno(qno)
Returns the trimmed value of the first input element for the specified question number.
Usage Scenario
const answer = getInputValueByQno('Q6');
console.log(answer);
Parameters
qno(string): Question number identifier (e.g.,"Q6") used to locate the survey question container.
Setup: Retrieve Postcode by Question Number
This function retrieves the value of a postcode input field within a survey question, identified by its question number (QNO). It only returns a value if the input is marked to contain a postcode.
-
getPostcodeByQno(qno)
Returns the trimmed value of the postcode input for the specified question number, ornullif not found or not applicable.
Usage Scenario
const postcode = getPostcodeByQno('Q10');
console.log(postcode);
Parameters
qno(string): Question number identifier (e.g.,"Q10") used to locate the survey question container.
Setup: Retrieve URL Parameter Value
This function retrieves the value of a query parameter from the current page URL. If the parameter is not present, it returns a default value.
-
getUrlParamValue(paramName, defaultValue = null)
Returns the trimmed value of the URL parameter specified byparamName. If the parameter does not exist, returnsdefaultValue.
Usage Scenario
const surveyId = getUrlParamValue('surveyId', 'defaultSurvey');
console.log(surveyId);
Parameters
paramName(string): The name of the URL query parameter to retrieve (e.g.,"surveyId").defaultValue(any, optional): The value to return if the parameter is not found. Defaults tonull.
Setup: Enable/Disable Input Fields by Question Number
This function dynamically enables or disables all input, textarea, and select fields for a given survey question identified by its question number (QNO). It also applies styling to indicate the disabled state.
-
setInputEnabledByQno(qno, isEnabled)
Enables or disables all form fields within the question container.
Usage Scenario
setInputEnabledByQno('Q6', false); // Disable all fields for Q6
setInputEnabledByQno('Q7', true); // Enable all fields for Q7
Parameters
qno(string): Question number identifier (e.g.,"Q6") used to locate the survey question container.isEnabled(boolean): Passtrueto enable the fields,falseto disable them.
Setup: Matrix Single-Answer Straight Check
This function checks for "straight-lining" in matrix single-answer questions. Straight-lining occurs when the respondent selects the same answer consecutively across multiple rows. If the maximum allowed consecutive identical answers is exceeded, an error message is displayed.
-
matrix_SingleAnswer_StraightCheck(qno, result, maxStraightItems)
Validates a matrix question to ensure no straight-lining beyond the allowed limit.
Usage Scenario
matrix_SingleAnswer_StraightCheck('Q12', '', 3); // Checks Q12 for 3 consecutive identical answers
Parameters
qno(string): Question number identifier (e.g.,"Q12").result(string): Pipe-delimited string of responses (e.g.,"1:A|2:A|3:B"). If empty, the function fetches the current answers automatically.maxStraightItems(number, optional): Maximum allowed consecutive identical answers. Defaults to the total number of items in the matrix.
Need More Help
- Support: Contact the support team for assistance.