1(function (global) { 2 'use strict'; 3 4 var RULES = { 5 name: { min: 2, max: 70 }, 6 subject: { min: 10, max: 100 }, 7 message: { min: 20, max: 1500 } 8 }; 9 10 var FIELD_LABELS = { 11 name: 'Name', 12 subject: 'Subject', 13 message: 'Message' 14 }; 15 16 var EMAIL_REGEX = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; 17 18 function getRule(fieldName, overrides) { 19 var baseRule = RULES[fieldName] || {}; 20 var overrideRule = overrides && overrides[fieldName] ? overrides[fieldName] : {}; 21 22 return { 23 min: typeof overrideRule.min === 'number' ? overrideRule.min : baseRule.min, 24 max: typeof overrideRule.max === 'number' ? overrideRule.max : baseRule.max 25 }; 26 } 27 28 function toText(value) { 29 if (value === null || value === undefined) { 30 return ''; 31 } 32 return String(value).trim(); 33 } 34 35 function inRange(value, min, max) { 36 var len = toText(value).length; 37 return len >= min && len <= max; 38 } 39 40 function validateName(value, ruleOverrides, required) { 41 var text = toText(value); 42 var rule = getRule('name', ruleOverrides); 43 44 if (required !== false && !text.length) { 45 return 'Please enter your name.'; 46 } 47 48 if (text.length && !inRange(text, rule.min, rule.max)) { 49 return 'Limit ' + rule.min + ' to ' + rule.max + ' characters.'; 50 } 51 return ''; 52 } 53 54 function validateEmail(value, required) { 55 var text = toText(value); 56 57 if (required !== false && !text.length) { 58 return 'Please enter your email.'; 59 } 60 61 if (text.length && !EMAIL_REGEX.test(text)) { 62 return 'Please enter a valid email address.'; 63 } 64 return ''; 65 } 66 67 function validateRequired(value, fieldLabel) { 68 var text = toText(value); 69 if (!text.length) { 70 return 'Please enter your ' + fieldLabel + '.'; 71 } 72 return ''; 73 } 74 75 function validateSubject(value, required, ruleOverrides) { 76 var text = toText(value); 77 var rule = getRule('subject', ruleOverrides); 78 79 if (!required && text.length === 0) { 80 return ''; 81 } 82 83 if (required && !text.length) { 84 return 'Please enter your subject.'; 85 } 86 87 if (text.length && !inRange(text, rule.min, rule.max)) { 88 return 'Limit ' + rule.min + ' to ' + rule.max + ' characters.'; 89 } 90 return ''; 91 } 92 93 function validateMessage(value, ruleOverrides, required) { 94 var text = toText(value); 95 var rule = getRule('message', ruleOverrides); 96 97 if (required !== false && !text.length) { 98 return 'Please enter your message.'; 99 } 100 101 if (text.length && !inRange(text, rule.min, rule.max)) { 102 return 'Limit ' + rule.min + ' to ' + rule.max + ' characters.'; 103 } 104 return ''; 105 } 106 107 function getLimitMessage(fieldName, value, ruleOverrides) { 108 var fieldRule = getRule(fieldName, ruleOverrides); 109 var fieldLabel = FIELD_LABELS[fieldName]; 110 var text = toText(value); 111 112 if (!fieldRule || !fieldRule.max || !fieldLabel) { 113 return ''; 114 } 115 116 if (text.length >= fieldRule.max) { 117 return fieldLabel + ' character limit reached (' + fieldRule.max + ').'; 118 } 119 120 return ''; 121 } 122 123 function validateForm(values, options) { 124 var opts = options || {}; 125 var subjectRequired = !!opts.subjectRequired; 126 var nameRequired = opts.nameRequired !== false; 127 var emailRequired = opts.emailRequired !== false; 128 var messageRequired = opts.messageRequired !== false; 129 var ruleOverrides = opts.ruleOverrides || {}; 130 131 var errors = { 132 name: validateName(values && values.name, ruleOverrides, nameRequired), 133 email: validateEmail(values && values.email, emailRequired), 134 subject: validateSubject(values && values.subject, subjectRequired, ruleOverrides), 135 message: validateMessage(values && values.message, ruleOverrides, messageRequired) 136 }; 137 138 var isValid = !errors.name && !errors.email && !errors.subject && !errors.message; 139 140 return { 141 isValid: isValid, 142 errors: errors, 143 rules: { 144 name: getRule('name', ruleOverrides), 145 subject: getRule('subject', ruleOverrides), 146 message: getRule('message', ruleOverrides) 147 } 148 }; 149 } 150 151 function autoResizeTextarea(element) { 152 if (!element) return; 153 154 element.style.minHeight = '70px'; 155 element.style.height = 'auto'; 156 element.style.height = Math.max(element.scrollHeight, 70) + 'px'; 157 } 158 159 function initTextareaAutoResize(selector) { 160 var textareas = document.querySelectorAll(selector); 161 162 textareas.forEach(function(textarea) { 163 textarea.style.minHeight = '70px'; 164 textarea.style.overflowY = 'hidden'; 165 textarea.style.resize = 'none'; 166 167 // Auto-resize on input 168 textarea.addEventListener('input', function() { 169 autoResizeTextarea(this); 170 }); 171 172 // Initial resize 173 autoResizeTextarea(textarea); 174 }); 175 } 176 177 function ensureErrorElement(fieldSelector, errSelector) { 178 var $field = global.jQuery(fieldSelector); 179 var $error = global.jQuery(errSelector); 180 181 if ($error.length) { 182 return $error; 183 } 184 185 $error = global.jQuery('<div class="field-error-message" style="display:none;color:red;font-size:14px;margin-top:4px;"></div>'); 186 187 if (errSelector && errSelector.charAt(0) === '#') { 188 $error.attr('id', errSelector.substring(1)); 189 } else if (errSelector && errSelector.charAt(0) === '.') { 190 $error.addClass(errSelector.substring(1)); 191 } 192 193 var $wrapper = $field.closest('.iti'); 194 if ($wrapper.length) { 195 $wrapper.after($error); 196 } else { 197 $field.after($error); 198 } 199 200 return $error; 201 } 202 203 function setFieldError(fieldSelector, errSelector, message) { 204 if (!global.jQuery) { 205 return; 206 } 207 208 var $field = global.jQuery(fieldSelector); 209 var $error = ensureErrorElement(fieldSelector, errSelector); 210 var $wrapper = $field.closest('.iti'); 211 212 if (message) { 213 $field.addClass('field-error'); 214 $wrapper.addClass('field-error-wrapper'); 215 $error.html(message).show(); 216 } else { 217 $field.removeClass('field-error'); 218 $wrapper.removeClass('field-error-wrapper'); 219 $error.html('').hide(); 220 } 221 } 222 223 function focusField(fieldSelector) { 224 var element = null; 225 226 if (global.jQuery) { 227 element = global.jQuery(fieldSelector).get(0); 228 } 229 230 if (!element && global.document) { 231 element = global.document.querySelector(fieldSelector); 232 } 233 234 if (!element) { 235 return; 236 } 237 238 if (typeof element.scrollIntoView === 'function') { 239 element.scrollIntoView({ behavior: 'smooth', block: 'center' }); 240 } 241 242 if (typeof element.focus === 'function') { 243 element.focus(); 244 } 245 246 if (typeof element.setSelectionRange === 'function' && typeof element.value === 'string') { 247 var cursorPosition = element.value.length; 248 element.setSelectionRange(cursorPosition, cursorPosition); 249 } 250 } 251 252 function focusFirstInvalidField(fieldOrder, errors) { 253 if (!fieldOrder || !errors) { 254 return; 255 } 256 257 fieldOrder.some(function(fieldConfig) { 258 if (!fieldConfig || !errors[fieldConfig.key]) { 259 return false;
260 } 261 262 focusField(fieldConfig.selector); 263 return true; 264 }); 265 } 266 267 function bindFieldClearOnInput(fieldErrorMap) { 268 if (!global.jQuery || !fieldErrorMap) { 269 return; 270 } 271 272 Object.keys(fieldErrorMap).forEach(function(fieldSelector) { 273 var errSelector = fieldErrorMap[fieldSelector]; 274 global.jQuery(fieldSelector).on('input', function() { 275 setFieldError(fieldSelector, errSelector, ''); 276 }); 277 }); 278 } 279 280 global.CommonFormValidation = { 281 rules: RULES, 282 validateName: validateName, 283 validateEmail: validateEmail, 284 validateRequired: validateRequired, 285 validateSubject: validateSubject, 286 validateMessage: validateMessage, 287 getLimitMessage: getLimitMessage, 288 validateForm: validateForm, 289 autoResizeTextarea: autoResizeTextarea, 290 initTextareaAutoResize: initTextareaAutoResize, 291 setFieldError: setFieldError, 292 focusField: focusField, 293 focusFirstInvalidField: focusFirstInvalidField, 294 bindFieldClearOnInput: bindFieldClearOnInput 295 }; 296})(window);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.