Client Scripts
Custom Date Range Validation
Validate date fields against each other with custom business rules like working days, blackout periods, and lead times.
function onChange(control, oldValue, newValue, isLoading, isTemplate) {
// Exit if form is loading
if (isLoading) {
return;
}
// Configuration
var minimumLeadTimeDays = 3; // Minimum days in advance
var minimumDurationHours = 1; // Minimum change window
var maximumDurationHours = 8; // Maximum change window
// Blackout periods (no changes allowed)
var blackoutPeriods = [
{start: '2024-12-24', end: '2024-12-26', reason: 'Holiday Freeze'},
{start: '2024-12-31', end: '2025-01-02', reason: 'New Year Freeze'}
];
// Restricted days (require additional approval)
var restrictedDays = [0, 6]; // Sunday = 0, Saturday = 6
// Get both date fields
var startDate = g_form.getValue('start_date');
var endDate = g_form.getValue('end_date');
// Clear previous messages
g_form.hideFieldMsg('start_date');
g_form.hideFieldMsg('end_date');
if (!startDate) {
return;
}
var start = new Date(startDate);
var now = new Date();
// Validation 1: Check minimum lead time
var leadTimeMs = start - now;
var leadTimeDays = leadTimeMs / (1000 * 60 * 60 * 24);
if (leadTimeDays < minimumLeadTimeDays) {
var message = 'Start date must be at least ' + minimumLeadTimeDays +
' days in advance. Current lead time: ' +
leadTimeDays.toFixed(1) + ' days.';
g_form.showFieldMsg('start_date', message, 'error');
g_form.addErrorMessage(message);
}
// Validation 2: Check if date is in the past
if (start < now) {
g_form.showFieldMsg('start_date', 'Start date cannot be in the past', 'error');
}
// Validation 3: Check blackout periods
for (var i = 0; i < blackoutPeriods.length; i++) {
var blackout = blackoutPeriods[i];
var blackoutStart = new Date(blackout.start);
var blackoutEnd = new Date(blackout.end);
if (start >= blackoutStart && start <= blackoutEnd) {
var message = 'Change cannot be scheduled during ' + blackout.reason +
' (' + blackout.start + ' to ' + blackout.end + ')';
g_form.showFieldMsg('start_date', message, 'error');
g_form.addErrorMessage(message);
}
}
// Validation 4: Check restricted days (weekends)
var dayOfWeek = start.getDay();
if (restrictedDays.indexOf(dayOfWeek) !== -1) {
var dayNames = ['Sunday', 'Monday', 'Tuesday', 'Wednesday',
'Thursday', 'Friday', 'Saturday'];
var message = 'Changes scheduled on ' + dayNames[dayOfWeek] +
' require additional approval';
g_form.showFieldMsg('start_date', message, 'warning');
g_form.addInfoMessage(message);
// Set flag for additional approval requirement
g_form.setValue('u_requires_additional_approval', 'true');
}
// Validation 5: Check business hours (e.g., 9 AM - 5 PM)
var hour = start.getHours();
var isBusinessHours = (hour >= 9 && hour < 17);
if (!isBusinessHours) {
g_form.showFieldMsg('start_date',
'After-hours change: Additional approval may be required',
'warning');
}
// Validation 6: Validate against end date if present
if (endDate) {
var end = new Date(endDate);
// End must be after start
if (end <= start) {
g_form.showFieldMsg('end_date', 'End date must be after start date', 'error');
} else {
// Check duration
var durationMs = end - start;
var durationHours = durationMs / (1000 * 60 * 60);
if (durationHours < minimumDurationHours) {
var message = 'Change window must be at least ' +
minimumDurationHours + ' hour(s)';
g_form.showFieldMsg('end_date', message, 'error');
}
if (durationHours > maximumDurationHours) {
var message = 'Change window exceeds maximum of ' +
maximumDurationHours + ' hours. ' +
'Consider breaking into multiple changes.';
g_form.showFieldMsg('end_date', message, 'warning');
}
// Show duration info
var durationInfo = 'Change window: ' + durationHours.toFixed(1) + ' hours';
g_form.showFieldMsg('end_date', durationInfo, 'info');
}
}
// Validation 7: Check for conflicts with other changes
// This would require GlideAjax call to check server-side
// Simplified example:
/*
var ga = new GlideAjax('ChangeConflictChecker');
ga.addParam('sysparm_name', 'checkConflicts');
ga.addParam('sysparm_start_date', startDate);
ga.addParam('sysparm_end_date', endDate);
ga.addParam('sysparm_ci', g_form.getValue('cmdb_ci'));
ga.getXMLAnswer(function(response) {
if (response === 'true') {
g_form.showFieldMsg('start_date',
'Warning: Another change is scheduled during this time',
'warning');
}
});
*/
}How to use it
1. Create onChange Client Scripts for both start_date and end_date fields 2. Customize minimumLeadTimeDays and duration limits for your policies 3. Update blackoutPeriods array with your freeze dates 4. Adjust restrictedDays for your organization (weekends, specific days) 5. Create duplicate script for end_date field 6. Consider adding GlideAjax call for conflict checking 7. Test all date scenarios including edge cases 8. Document validation rules for users
Adapt the table names, fields, and conditions to your instance. Test the behavior in a development environment before using it in production.