-
Notifications
You must be signed in to change notification settings - Fork 33
[codex] Add pre-chat regex validation support #1522
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: development
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -359,6 +359,44 @@ var KMPreChat = (function () { | |
| } | ||
| } | ||
|
|
||
| var getCustomValidation = function (preLeadCollection) { | ||
| var validation = preLeadCollection && preLeadCollection.validation; | ||
| if (!validation || !validation.regex) { | ||
| return null; | ||
| } | ||
| var regex = validation.regex; | ||
| var flags = ''; | ||
| if (regex instanceof RegExp) { | ||
| flags = regex.flags; | ||
| regex = regex.source; | ||
|
Comment on lines
+369
to
+371
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
When a widget config passes Useful? React with 👍 / 👎. |
||
| } | ||
| if (typeof regex !== 'string') { | ||
| return null; | ||
| } | ||
| return { | ||
| regex: regex, | ||
| flags: flags, | ||
| errorText: | ||
| validation.errorText || getLeadCollectionLabel('commonErrorMsg', ''), | ||
| }; | ||
| }; | ||
|
|
||
| var setValidationAttributes = function (input, validation) { | ||
| if (!input || !validation || !validation.regex) { | ||
| return; | ||
| } | ||
| input.setAttribute('pattern', validation.regex); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Although the new data attribute now preserves Useful? React with 👍 / 👎. |
||
| input.setAttribute('title', validation.errorText || ''); | ||
| input.setAttribute('data-km-validation-regex', validation.regex); | ||
| input.setAttribute('data-km-validation-flags', validation.flags || ''); | ||
| input.setAttribute('data-km-validation-error', validation.errorText || ''); | ||
| input.setAttribute( | ||
| 'oninvalid', | ||
| "setCustomValidity(this.getAttribute('data-km-validation-error') || '')" | ||
| ); | ||
| input.setAttribute('oninput', "setCustomValidity('')"); | ||
| }; | ||
|
|
||
| target.createInputField = function (preLeadCollection) { | ||
| var rawField = (preLeadCollection.field || '').toString(); | ||
| var normalizedField = rawField.toLowerCase().replace(/\s+/g, ''); | ||
|
|
@@ -427,7 +465,10 @@ var KMPreChat = (function () { | |
| kmChatInput.setAttribute('type', preLeadCollection.type || 'text'); | ||
| kmChatInput.setAttribute('placeholder', preLeadCollection.placeholder || ''); | ||
| kmChatInput.setAttribute('aria-label', preLeadCollection.field); | ||
| if (preLeadCollection.type === 'email') { | ||
| var customValidation = getCustomValidation(preLeadCollection); | ||
| if (customValidation) { | ||
| setValidationAttributes(kmChatInput, customValidation); | ||
| } else if (preLeadCollection.type === 'email') { | ||
| kmChatInput.setAttribute('pattern', '^[^\\s@]+@[^\\s@]+\\.[^\\s@]{2,}$'); | ||
| kmChatInput.setAttribute('title', ''); | ||
| kmChatInput.setAttribute( | ||
|
|
@@ -645,6 +686,10 @@ var KMPreChat = (function () { | |
| var emailField = document.getElementById('km-email'); | ||
| var phoneField = document.getElementById('km-phone'); | ||
| var submitBtn = document.getElementById('km-submit-chat-login'); | ||
| var chatLoginForm = document.getElementById('km-form-chat-login'); | ||
| var customValidationFields = Array.prototype.slice.call( | ||
| document.querySelectorAll('[data-km-validation-regex]') | ||
| ); | ||
| var formSubmitted = false; | ||
|
|
||
| var setError = function (message) { | ||
|
|
@@ -660,24 +705,73 @@ var KMPreChat = (function () { | |
| } | ||
| }; | ||
|
|
||
| var validateCustomField = function (field) { | ||
| var regexText = field.getAttribute('data-km-validation-regex'); | ||
| var regexFlags = field.getAttribute('data-km-validation-flags') || ''; | ||
| var errorText = | ||
| field.getAttribute('data-km-validation-error') || | ||
| getLeadCollectionLabel('commonErrorMsg', ''); | ||
| if (!regexText) { | ||
| return true; | ||
| } | ||
| var value = field.value || ''; | ||
| if (!value && !field.hasAttribute('required')) { | ||
| return true; | ||
| } | ||
| try { | ||
| if (!new RegExp(regexText, regexFlags).test(value)) { | ||
| setError(errorText); | ||
| return false; | ||
| } | ||
| } catch (error) { | ||
| console.error('Invalid pre-chat validation regex', error); | ||
| setError(errorText); | ||
| return false; | ||
| } | ||
|
coderabbitai[bot] marked this conversation as resolved.
|
||
| return true; | ||
| }; | ||
|
|
||
| var handleCustomValidation = function () { | ||
| if (!formSubmitted) { | ||
| return true; | ||
| } | ||
| for (var i = 0; i < customValidationFields.length; i++) { | ||
| if (!validateCustomField(customValidationFields[i])) { | ||
| return false; | ||
| } | ||
| } | ||
| return true; | ||
| }; | ||
|
|
||
| customValidationFields.forEach(function (field) { | ||
| field.addEventListener('input', function () { | ||
| handleCustomValidation(); | ||
| }); | ||
| field.addEventListener('blur', function () { | ||
| handleCustomValidation(); | ||
| }); | ||
| }); | ||
|
|
||
| if (emailField) { | ||
| var isValidEmail = function (value) { | ||
| return KommunicateUI.isValidEmail(value); | ||
| }; | ||
| var handleEmailValidation = function () { | ||
| if (!formSubmitted) { | ||
| return; | ||
| return true; | ||
| } | ||
| var value = (emailField.value || '').toLowerCase(); | ||
| if (!value) { | ||
| setError(''); | ||
| return; | ||
| return true; | ||
| } | ||
| if (!isValidEmail(value)) { | ||
| setError(getLeadCollectionLabel('errorEmail', '')); | ||
| return false; | ||
| } else { | ||
| setError(''); | ||
| } | ||
| return true; | ||
| }; | ||
| emailField.addEventListener('input', function () { | ||
| handleEmailValidation(); | ||
|
|
@@ -690,12 +784,12 @@ var KMPreChat = (function () { | |
| if (phoneField) { | ||
| var handlePhoneValidation = function () { | ||
| if (!formSubmitted) { | ||
| return; | ||
| return true; | ||
| } | ||
| var value = phoneField.value || ''; | ||
| if (!value) { | ||
| setError(''); | ||
| return; | ||
| return true; | ||
| } | ||
| var isValid = true; | ||
| var intlInstance = deps.getIntlTelInstance(); | ||
|
|
@@ -707,9 +801,11 @@ var KMPreChat = (function () { | |
| } | ||
| if (!isValid) { | ||
| setError(getLeadCollectionLabel('commonErrorMsg', '')); | ||
| return false; | ||
| } else { | ||
| setError(''); | ||
| } | ||
| return true; | ||
| }; | ||
| phoneField.addEventListener('input', function () { | ||
| handlePhoneValidation(); | ||
|
|
@@ -719,12 +815,27 @@ var KMPreChat = (function () { | |
| }); | ||
| } | ||
|
|
||
| var handleSubmitValidation = function (event) { | ||
| formSubmitted = true; | ||
| if ( | ||
| !handleCustomValidation() || | ||
| (handleEmailValidation && !handleEmailValidation()) || | ||
| (handlePhoneValidation && !handlePhoneValidation()) | ||
| ) { | ||
| if (event && typeof event.preventDefault === 'function') { | ||
| event.preventDefault(); | ||
| } | ||
| return false; | ||
| } | ||
| setError(''); | ||
| return true; | ||
| }; | ||
|
|
||
| if (submitBtn) { | ||
| submitBtn.addEventListener('click', function () { | ||
| formSubmitted = true; | ||
| handleEmailValidation && handleEmailValidation(); | ||
| handlePhoneValidation && handlePhoneValidation(); | ||
| }); | ||
| submitBtn.addEventListener('click', handleSubmitValidation); | ||
| } | ||
| if (chatLoginForm) { | ||
| chatLoginForm.addEventListener('submit', handleSubmitValidation); | ||
| } | ||
| }; | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Guard clipboard access before calling
getData()Line 4366 can throw when clipboard APIs are unavailable, which breaks paste handling entirely in affected environments. Add a safe fallback before
.replace(...).Proposed fix
📝 Committable suggestion
🤖 Prompt for AI Agents