This script is written for a NetSuite Client Script and performs several tasks related to field validation, focusing on mandatory fields, and ensuring the user can easily correct missing or invalid inputs.
Key Functionalities:
- Highlight and Focus on Missing Fields:
- The script highlights mandatory fields that are missing a value during the save operation.
- It updates the background color of the label of the missing field (not the input box) to indicate the error. It also focuses on the field after a brief delay, ensuring the user is directed to the appropriate input field.
- Field Validation:
- Mandatory Fields Validation: Before the record is saved, the script checks if all mandatory fields have been filled out. If any mandatory fields are missing, it:
- Highlights and focuses on the first missing field.
- Prevents the record from saving by returning
falseif there are any issues. - This validation occurs in the
saveRecordfunction, which loops through the list of mandatory fields and verifies whether each one has a value.
- Loading Mandatory Fields:
- The script dynamically loads all mandatory fields from the current record using the NetSuite Record module. It collects all the fields marked as mandatory and stores them in a global object called
MANDATORY_FIELDS. This list is then used for validation during the save process.
- Subtab Navigation:
- If a mandatory field is located in a different tab, the script automatically switches to the correct subtab where the field is located. It ensures that the correct tab is selected so the user can see and interact with the field.
- The
findTabNameByFieldfunction is responsible for finding the tab name where the field is located by querying the DOM structure.
- Focus Management:
- The function
focusFieldhandles scrolling the field into view and focusing on it. If necessary, it also triggers the activation of the subtab containing the field. After focusing, the background of the label is highlighted to visually indicate the issue.
- Field Focus Logic:
- The
highlightAndFocusFieldfunction ensures that after locating the field, it will: - Apply a light red background color to the field’s label.
- Set focus to the field (either input or textarea) after a short delay, ensuring that the cursor is placed where the user can enter data.
- If the field is an input or textarea, the cursor is explicitly placed at the beginning of the field to give the user a clear indication of where to start typing.
Breakdown of Key Functions:
highlightAndFocusField(fieldElement, fieldName): Highlights the field label and sets focus on the field.saveRecord(context): Validates the mandatory fields, focusing on any missing fields and preventing save if any mandatory fields are not filled.getMandatoryFields(): Loads and stores all mandatory fields from the current record.pageInit(context): Initializes the script by loading mandatory fields when the page is loaded.findTabNameByField(fieldId): Finds the tab containing a specific field by checking the DOM structure and thedata-tab-nameattribute.focusField(fieldId): Focuses on a field and ensures that the appropriate subtab is selected.
Summary:
The script ensures that:
- Mandatory fields are validated before saving.
- Missing fields are visually highlighted, and the user is directed to the field.
- Subtabs are automatically activated if a field is in a different tab.
- Focus management is handled to give the user a smooth, clear experience when filling out the form.
/**
* @NApiVersion 2.1
* @NScriptType ClientScript
* @NModuleScope SameAccount
*/
/***********
* STERI-4 SteriTek-USA-NS
*
* STERI-4 : Service Order Mandatory field focusing.
*
*
**************************************************************************************
********
*
* Author: Jobin and Jismi IT Services
*
* Date Created : 1-January-2025
*
* Description : This script is used to focus the fields that are mandatory and missed by the user to enter.
*
* REVISION HISTORY
*
* @version 1.0 STERI-902 : 1-january : Created the initial build by JJ0199
* **************************************************************************************
* **/
define([‘N/currentRecord’, ‘N/record’], (currentRecordModule, record) => {
let MANDATORY_FIELDS = {};
/**
* Highlights the missing field with custom styles and focuses it.
* @param {HTMLElement} fieldElement – The DOM element of the field.
* @param {string} fieldName – The display name of the field.
*/
function highlightAndFocusField(fieldElement, fieldName) {
if (fieldElement) {
const labelElement = fieldElement.closest(‘tr’).querySelector(`[data-nsps-type=”label”]`);
if (labelElement) {
labelElement.style.backgroundColor = ‘#ffe6e6’;
setTimeout(() => {
fieldElement.focus();
if (fieldElement.tagName.toLowerCase() === ‘input’ || fieldElement.tagName.toLowerCase() === ‘textarea’) {
fieldElement.selectionStart = fieldElement.selectionEnd = 0;
}
}, 300);
}
fieldElement.focus();
}
}
/**
* Validates mandatory fields before saving the record.
* @returns {boolean} True if validation passes, false otherwise.
*/
function saveRecord(context) {
console.log(“MANDATORY_FIELDS”, MANDATORY_FIELDS);
const currentRecord = context.currentRecord;
let isValid = true;
let firstMissingFieldId = null;
for (const fieldId in MANDATORY_FIELDS) {
const fieldElement = document.querySelector(`[name=”${fieldId}“]`);
if (fieldElement) {
fieldElement.style.backgroundColor = ”;
fieldElement.style.border = ”;
const noteIcon = fieldElement.parentElement.querySelector(‘.mandatory-note’);
if (noteIcon) {
noteIcon.remove();
}
}
}
for (const [fieldId, fieldConfig] of Object.entries(MANDATORY_FIELDS)) {
const fieldValue = currentRecord.getValue({ fieldId });
if (!fieldValue) {
if (!firstMissingFieldId) {
firstMissingFieldId = fieldId;
}
focusField(fieldId)
isValid = false;
}
}
return isValid;
}
/**
* Get all mandatory fields on the record.
* @returns {Array} List of mandatory field IDs.
*/
function getMandatoryFields() {
const currentRecord = currentRecordModule.get().id;
const recordObj = record.load({
type: currentRecordModule.get().type,
id: currentRecord
});
const allFields = recordObj.getFields();
allFields.forEach((fieldId) => {
const field = currentRecordModule.get().getField({ fieldId });
if (field && field.isMandatory) {
MANDATORY_FIELDS ? MANDATORY_FIELDS = {
…MANDATORY_FIELDS,
[fieldId]: field.label
} : {
[fieldId]: field.label
}
}
});
}
function pageInit(context) {
getMandatoryFields();
console.log(‘Mandatory Fields:’);
}
/**
* Finds the tab name (data-tab-name) of the tab containing a specific field.
* @param {string} fieldId – The field’s internal ID.
* @returns {string|null} The tab name (data-tab-name) if found, otherwise null.
*/
function findTabNameByField(fieldId) {
const fieldElement = document.querySelector(`[data-field-name=”${fieldId}“]`);
console.log(“fieldElement”, fieldElement);
if (fieldElement) {
const tabTable = fieldElement.closest(‘table.uir-tab-fields’);
console.log(“tabTable”, tabTable);
if (tabTable && tabTable.hasAttribute(‘data-tab-name’)) {
console.log(“tabTable.getAttribute(‘data-tab-name’)”, tabTable.getAttribute(‘data-tab-name’));
return tabTable.getAttribute(‘data-tab-name’);
}
}
return null;
}
/**
* Focus a field in NetSuite, including handling subtabs.
* @param {string} fieldId – The internal ID of the field to focus on.
*/
function focusField(fieldId) {
const fieldElement = document.querySelector(`[data-field-name=”${fieldId}“]`);
console.log(“fieldElement”, fieldElement);
if (fieldElement) {
const subtabId = findTabNameByField(fieldId);
console.log(“subtabId”, subtabId);
if (subtabId && subtabId !== “main”) {
document.querySelector(`[data-nsps-id=”${subtabId}“]`).click();
} else if (subtabId == “main”) {
document.querySelector(`[data-nsps-id=”custom147″]`).click();
}
fieldElement.scrollIntoView({ behavior: ‘smooth’, block: ‘center’ });
highlightAndFocusField(fieldElement, “”)
} else {
console.log(“Field not found:”, fieldId);
}
}
return {
saveRecord,
pageInit
};
});