{"version":3,"file":"../checkout-validation-300.min.js","sources":["checkout-validation-300.js"],"sourcesContent":["/**\n * Manage checkout front-end validation.\n *\n * DEPENDS ON:\n * - jQuery // Interact with WooCommerce events\n */\n\n(function (root, factory) {\n\tif ( typeof define === 'function' && define.amd ) {\n\t\tdefine([], factory(root));\n\t} else if ( typeof exports === 'object' ) {\n\t\tmodule.exports = factory(root);\n\t} else {\n\t\troot.CheckoutValidation = factory(root);\n\t}\n})(typeof global !== 'undefined' ? global : this.window || this.global, function (root) {\n\n\t'use strict';\n\n\tvar $ = jQuery;\n\tvar _hasJQuery = ( $ != null );\n\n\tvar _hasInitialized = false;\n\tvar _publicMethods = {};\n\tvar _validationTypes = {};\n\tvar _settings = {\n\t\tbodyClass: 'fc-checkout-validation--active',\n\t\tformSelector: 'form.checkout',\n\t\tformRowSelector: '.form-row, .shipping-method__package',\n\t\tinputWrapperSelector: '.woocommerce-input-wrapper',\n\t\tvalidateFieldsSelector: '.input-text, select, .shipping-method__options',\n\t\treferenceNodeSelector: '.input-text, select, .shipping-method__options', // Usually same as `validateFieldsSelector`\n\t\tclearValidationCountryChangedSelector: '#state, #shipping_state, #billing_state',\n\t\talwaysValidateFieldsSelector: '',\n\t\tselect2Selector: '.select2, .select2-hidden-accessible',\n\n\t\ttypeRequiredSelector: '.validate-required',\n\t\ttypeEmailSelector: '.validate-email',\n\t\ttypeConfirmationSelector: '[data-confirm-with]',\n\t\ttypeShippingMethodSelector: '.shipping-method__package',\n\t\t\n\t\tvalidClass: 'woocommerce-validated',\n\t\tinvalidClass: 'woocommerce-invalid',\n\n\t\tvalidationMessages: {\n\t\t\trequired: 'This is a required field.',\n\t\t\temail: 'This is not a valid email address.',\n\t\t\tconfirmation: 'This field does not match the related field value.',\n\t\t},\n\t};\n\n\n\n\t/**\n\t * METHODS\n\t */\n\t\n\n\n\t/**\n\t * Check if field is hidden to the user.\n\t * @param {Field} field Field to test visibility.\n\t * @return {Boolean} True if field is hidden to the user.\n\t */\n\tvar isFieldHidden = function( field ) {\n\t\treturn ( field.offsetParent === null );\n\t};\n\n\n\n\t/**\n\t * Check if field is in allow list for always validate.\n\t * @param {Field} field Field to test for allow list.\n\t * @return {Boolean} True if field is in allow list for always validate.\n\t */\n\tvar isAlwaysValidate = function( field ) {\n\t\t// Bail if field not found or selector empty\n\t\tif ( ! field || ! _settings.alwaysValidateFieldsSelector ) { return false; }\n\n\t\t// Check if field is in allow list\n\t\tif ( field.matches( _settings.alwaysValidateFieldsSelector ) ) { return true; }\n\t\treturn false;\n\t};\n\n\t\n\n\t/**\n\t * Get the form-row element related to the field.\n\t * @param {Field} field Form field.\n\t * @return {Element} Form row related to the passed field.\n\t */\n\tvar getFormRow = function( field ) {\n\t\t// Bail if field not valid\n\t\tif ( !field ) { return; }\n\n\t\treturn field.closest( _settings.formRowSelector );\n\t};\n\n\n\n\t/**\n\t * Add markup for inline message of required fields.\n\t * @param {Field} field Field to validate.\n\t * @param {Element} formRow Form row related to the field.\n\t * @param {String} message Message to add.\n\t * @param {String} invalidClass Type of error used to identify which message is related to which error.\n\t */\n\tvar addInlineMessage = function( field, formRow, message, invalidClass ) {\n\t\t// Bail if field not valid\n\t\tif ( ! field ) { return; }\n\n\t\t// Bail if message is empty\n\t\tif ( ! message || message.length == 0 ) { return; }\n\n\t\tvar inputWrapper = field.closest( _settings.inputWrapperSelector );\n\t\tvar referenceNode = inputWrapper.querySelector( _settings.referenceNodeSelector );\n\n\t\t// Change reference field for select2\n\t\tif ( isSelect2Field( field ) ) {\n\t\t\tvar newReference = field.parentNode.querySelector( '.select2-container' );\n\t\t\tif ( newReference ) { referenceNode = newReference; }\n\t\t}\n\n\t\t// Create message element and add it after the field.\n\t\tvar parent = referenceNode.parentNode;\n\t\tvar element = document.createElement( 'span' );\n\t\telement.className = 'woocommerce-error invalid-' + invalidClass;\n\t\telement.innerText = message;\n\t\tparent.insertBefore( element, referenceNode.nextSibling );\n\t};\n\n\n\t/**\n\t * Remove inline message from the field.\n\t * @param {Field} field Field to validate.\n\t * @param {Element} formRow Form row related to the field.\n\t * @param {String} invalidClass Type of error used to identify which message is related to which error.\n\t */\n\tvar removeInlineMessage = function( field, formRow, invalidClass ) {\n\t\tvar messageElements = formRow.querySelectorAll( 'span.woocommerce-error.invalid-' + invalidClass );\n\t\tfor ( var i = 0; i < messageElements.length; i++ ) {\n\t\t\tmessageElements[ i ].parentNode.removeChild( messageElements[ i ] );\n\t\t}\n\t}\n\n\t\n\n\t/**\n\t * Check field is a select2 element.\n\t * @param {Field} field Field to check.\n\t * @return {Boolean} True if field is select2.\n\t */\n\tvar isSelect2Field = function( field ) {\n\t\tif ( field.closest( _settings.select2Selector ) ) { return true; }\n\t\treturn false;\n\t};\n\n\n\n\t/**\n\t * Check if field is a select field.\n\t * @param {Element} field Field to check.\n\t * @return {Boolean} True if is a select field.\n\t */\n\tvar isSelectField = function( field ) {\n\t\tif ( field.matches( 'select' ) ) { return true; }\n\t\treturn false;\n\t};\n\n\n\n\t/**\n\t * Check if field has value.\n\t * @param {Field} field Field to check.\n\t * @return {Boolean} True if field has value.\n\t */\n\t_publicMethods.hasValue = function( field ) {\n\t\t// Check for select 2 field\n\t\tif ( isSelectField( field ) ) {\n\t\t\tif ( field.options && field.selectedIndex > -1 && field.options[ field.selectedIndex ].value != '' ) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\telse {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\t// Check for all other fields\n\t\tif ( field.value != '' ) { return true; }\n\t\t\n\t\treturn false;\n\t};\n\n\n\n\t/**\n\t * Check if form row is required.\n\t * @param {Field} field Field for validation.\n\t * @param {Element} formRow Form row element.\n\t * @param {String} validationEvent Event that triggered the validation.\n\t * @return {Boolean} Whether the field is required or not.\n\t */\n\tvar isRequiredField = function( field, formRow, validationEvent ) {\n\t\tif ( ! formRow.matches( _settings.typeRequiredSelector ) ) { return false; }\n\t\treturn true;\n\t};\n\n\t/**\n\t * Validate required field.\n\t * @param {Field} field Field for validation.\n\t * @param {Element} formRow Form row element.\n\t * @param {String} validationEvent Event that triggered the validation.\n\t * @return {Boolean} Whether the required field has a value or not.\n\t */\n\tvar validateRequired = function( field, formRow, validationEvent ) {\n\t\t// Bail if field does not have a value\n\t\tif ( ! _publicMethods.hasValue( field ) ) { return { valid: false, message: _settings.validationMessages.required }; }\n\n\t\treturn { valid: true };\n\t};\n\n\n\n\t/**\n\t * Check if form row is email field.\n\t * @param {Field} field Field for validation.\n\t * @param {Element} formRow Form row element.\n\t * @param {String} validationEvent Event that triggered the validation.\n\t * @return {Boolean} Whether the field is an email address field.\n\t */\n\tvar isEmailField = function( field, formRow, validationEvent ) {\n\t\tif ( ! formRow.matches( _settings.typeEmailSelector ) ) { return false; }\n\t\treturn true;\n\t};\n\n\t/**\n\t * Validate email field.\n\t * @param {Field} field Field for validation.\n\t * @param {Element} formRow Form row element.\n\t * @param {String} validationEvent Event that triggered the validation.\n\t * @return {Boolean} Whether the field has a valid email address value.\n\t */\n\tvar validateEmail = function( field, formRow, validationEvent ) {\n\t\t// Bail if does not have value\n\t\tif ( ! _publicMethods.hasValue( field ) ) { return { valid: true }; }\n\n\t\t/* https://stackoverflow.com/questions/2855865/jquery-validate-e-mail-address-regex */\n\t\tvar emailPattern = new RegExp(/^((([a-z]|\\d|[!#\\$%&'\\*\\+\\-\\/=\\?\\^_`{\\|}~]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])+(\\.([a-z]|\\d|[!#\\$%&'\\*\\+\\-\\/=\\?\\^_`{\\|}~]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])+)*)|((\\x22)((((\\x20|\\x09)*(\\x0d\\x0a))?(\\x20|\\x09)+)?(([\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x7f]|\\x21|[\\x23-\\x5b]|[\\x5d-\\x7e]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(\\\\([\\x01-\\x09\\x0b\\x0c\\x0d-\\x7f]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF]))))*(((\\x20|\\x09)*(\\x0d\\x0a))?(\\x20|\\x09)+)?(\\x22)))@((([a-z]|\\d|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(([a-z]|\\d|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])([a-z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])*([a-z]|\\d|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])))\\.)+(([a-z]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(([a-z]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])([a-z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])*([a-z]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])))\\.?$/i);\n\n\t\t// Validate email value\n\t\tif ( ! emailPattern.test( field.value ) ) { return { valid: false, message: _settings.validationMessages.email }; }\n\n\t\treturn { valid: true };\n\t};\n\n\n\n\t/**\n\t * Check if form row is a confirmation field.\n\t * @param {Field} field Field for validation.\n\t * @param {Element} formRow Form row element.\n\t * @param {String} validationEvent Event that triggered the validation.\n\t * @return {Boolean} Whether the field is a confirmation field that is related to another field in the form.\n\t */\n\tvar isConfirmationField = function( field, formRow, validationEvent ) {\n\t\tif ( ! formRow.querySelector( _settings.typeConfirmationSelector ) ) { return false; }\n\t\treturn true;\n\t};\n\n\t/**\n\t * Validate confirmation field.\n\t * @param {Field} field Field for validation.\n\t * @param {Element} formRow Form row element.\n\t * @param {String} validationEvent Event that triggered the validation.\n\t * @return {Boolean} Whether the confirmation field has the same value as the field it is related to.\n\t */\n\tvar validateConfirmation = function( field, formRow, validationEvent ) {\n\t\t// Bail if does not have value\n\t\tif ( ! _publicMethods.hasValue( field ) ) { return { valid: false }; }\n\n\t\t// Get confirmation field\n\t\tvar form = formRow.closest( 'form' );\n\t\tvar confirmWith = form ? form.querySelector( field.getAttribute( 'data-confirm-with' ) ) : null;\n\n\t\t// Validate fields have same value\n\t\tif ( confirmWith && field.value == confirmWith.value ) { return { valid: false, message: _settings.validationMessages.confirmation }; }\n\n\t\treturn { valid: true };\n\t};\n\n\t/**\n\t * Check if the form row is a shipping method field wrapper.\n\t * @param {Field} field Field for validation.\n\t * @param {Element} formRow Form row element.\n\t * @param {String} validationEvent Event that triggered the validation.\n\t * @return {Boolean} Whether the form row is a shipping method field wrapper.\n\t */\n\t var isShippingMethodField = function( field, formRow, validationEvent ) {\n\t\tif ( ! formRow.matches( _settings.typeShippingMethodSelector ) ) { return false; }\n\t\treturn true;\n\t};\n\n\t/**\n\t * Validate shipping method field.\n\t * @param {Field} field Field for validation.\n\t * @param {Element} formRow Form row element.\n\t * @param {String} validationEvent Event that triggered the validation.\n\t * @return {Boolean} Whether a shipping method has been selected in the form row.\n\t */\n\tvar validateShippingMethod = function( field, formRow, validationEvent ) {\n\t\tvar selectedShippingMethod = formRow.querySelector( 'input[type=\"radio\"]:checked' );\n\n\t\t// Bail if field does not have a value\n\t\tif ( ! selectedShippingMethod ) { return { valid: false, message: _settings.validationMessages.required }; }\n\n\t\treturn { valid: true };\n\t};\n\n\n\n\t/**\n\t * Check if field needs validation.\n\t * @param {Field} field Field to validate.\n\t * @param {Element} formRow Form row for validation.\n\t * @param {String} validationEvent Event that triggered the validation.\n\t * @return {Boolean} True if field needs any validation.\n\t */\n\tvar needsValidation = function( field, formRow, validationEvent ) {\n\t\t// Bail if field should always validate\n\t\tif ( isAlwaysValidate( field ) ) { return true; }\n\n\t\t// Test if field needs validation from any validation type\n\t\tvar validationTypeNames = Object.getOwnPropertyNames( _validationTypes );\n\t\tfor ( var i = 0; i < validationTypeNames.length; i++) {\n\t\t\tvar validationTypeName = validationTypeNames[i];\n\t\t\tvar validationType = _validationTypes[ validationTypeName ];\n\t\t\tif ( validationType.needsValidation( field, formRow, validationEvent ) ) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t};\n\n\n\n\t/**\n\t * Process validation results of a field.\n\t * @param {Field} field Field to validation.\n\t * @param {Element} formRow Form row element.\n\t * @param {Array} validationResults Validation results array.\n\t * @return {Boolean} True if all fields are valid.\n\t */\n\tvar processValidationResults = function( field, formRow, validationResults ) {\n\t\tvar valid = true;\n\n\t\t// Iterate validation results\n\t\tvar validationResultsNames = Object.getOwnPropertyNames( validationResults );\n\t\tfor ( var i = 0; i < validationResultsNames.length; i++ ) {\n\t\t\tvar validationTypeName = validationResultsNames[ i ];\n\t\t\tvar validationType = _validationTypes[ validationTypeName ];\n\t\t\tvar result = validationResults[ validationTypeName ].valid;\n\t\t\tvar message = validationResults[ validationTypeName ].message;\n\t\t\tvar invalidClass = validationType.invalidClass;\n\n\t\t\t// Remove class and message for the current validation type\n\t\t\tformRow.classList.remove( _settings.invalidClass +'-'+ validationType.invalidClass );\n\t\t\tremoveInlineMessage( field, formRow, invalidClass );\n\n\t\t\t// Maybe set field as invalid\n\t\t\tif ( true !== result ) {\n\t\t\t\tvalid = false;\n\n\t\t\t\t// Maybe display inline message and set field as invalid\n\t\t\t\tif ( null !== result ) {\n\t\t\t\t\taddInlineMessage( field, formRow, message, invalidClass );\n\n\t\t\t\t\t// Add field validation invalid classes for the validation type\n\t\t\t\t\tformRow.classList.add( _settings.invalidClass +'-'+ validationType.invalidClass );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Toggle general field valid/invalid classes\n\t\tformRow.classList.toggle( _settings.validClass, valid );\n\t\tformRow.classList.toggle( _settings.invalidClass, ! valid );\n\n\t\treturn valid;\n\t};\n\n\n\n\t/**\n\t * Clear the state fields validation status classes when the field loses the value due changes to the country fields.\n\t *\n\t * @param jQuery.Event event Event object as a `jQuery.Event`.\n\t * @param string country Selected country code value of the related country field.\n\t * @param jQuery.fn wrapper jQuery object representing the field wrapper element related to the country field that was changed. See variable `wrapper_selectors` ~LN103 of the `country-select.js`.\n\t */\n\tvar maybeClearStateFields = function( event, country, wrapper ) {\n\t\t// Bail if jQuery is not available\n\t\tif ( ! _hasJQuery ) { return; }\n\t\t\n\t\tvar wrappersList = $( wrapper ).toArray();\n\n\t\twrappersList.forEach( function( wrapperItem ) {\n\t\t\t\n\t\t\tvar fields = Array.from( wrapperItem.querySelectorAll( _settings.clearValidationCountryChangedSelector ) );\n\t\t\t\n\t\t\tfields.forEach( function( field ) {\n\t\t\t\t\n\t\t\t\tif ( '' == field.value ) {\n\t\t\t\t\tvar formRow = field.closest( _settings.formRowSelector );\n\t\t\t\t\t_publicMethods.clearValidationResults( field, formRow );\n\t\t\t\t}\n\n\t\t\t} );\n\n\t\t} );\n\t};\n\n\n\n\t/**\n\t * Handle document clicks and route to the appropriate function.\n\t */\n\tvar handleValidateEvent = function( e ) {\n\t\tvar field = e.target;\n\n\t\t// Get correct field when is select2\n\t\tif ( isSelect2Field( e.target ) ) {\n\t\t\tvar formRow = e.target.closest( _settings.formRowSelector );\n\n\t\t\tif ( formRow ) {\n\t\t\t\tfield = formRow.querySelector( 'select' );\n\t\t\t}\n\t\t}\n\n\t\t_publicMethods.validateField( field, e.type );\n\t};\n\n\n\n\t/**\n\t * Register validation types.\n\t */\n\tvar registerValidationTypes = function() {\n\t\t_publicMethods.registerValidationType( 'required', 'required-field', isRequiredField, validateRequired );\n\t\t_publicMethods.registerValidationType( 'email', 'email', isEmailField, validateEmail );\n\t\t_publicMethods.registerValidationType( 'confirmation', 'confirmation-field', isConfirmationField, validateConfirmation );\n\t\t_publicMethods.registerValidationType( 'shipping-method', 'shipping-method-field', isShippingMethodField, validateShippingMethod );\n\t}\n\n\n\n\t/**\n\t * Clear validation results status of a field.\n\t * @param {Field} field Field to validation.\n\t * @param {Element} formRow Form row element.\n\t */\n\t _publicMethods.clearValidationResults = function( field, formRow ) {\n\t\t// Bail if field or form row invalid\n\t\tif ( ! field || ! formRow ) { return; }\n\t\t\n\t\t// Remove invalid classes for validation types\n\t\tvar validationTypeKeys = Object.keys( _validationTypes );\n\t\tfor ( var i = 0; i < validationTypeKeys.length; i++ ) {\n\t\t\tvar type = validationTypeKeys[i];\n\t\t\tformRow.classList.remove( _settings.invalidClass +'-'+ type );\n\t\t\tformRow.classList.remove( _settings.invalidClass +'-'+ type + '-field' );\n\t\t}\n\n\t\t// Remove valid/invalid classes\n\t\tformRow.classList.remove( _settings.validClass );\n\t\tformRow.classList.remove( _settings.invalidClass );\n\t};\n\n\n\n\t/**\n\t * Test multiple validations on the passed field.\n\t * @param {Field} field Field for validation.\n\t * @return {String} Event that triggered the field validation. Can also be an arbitrary event name.\n\t * @return {Boolean} True if field is valid.\n\t */\n\t_publicMethods.validateField = function( field, validationEvent, validateHidden ) {\n\t\t// Bail if field is null\n\t\tif ( ! field ) { return true; }\n\n\t\tvar validationResults = {},\n\t\t\tformRow = getFormRow( field );\n\n\t\t// Bail if formRow not found\n\t\tif ( ! formRow ) { return true; }\n\n\t\t// Bail if hidden to the user\n\t\tif ( ! isAlwaysValidate( field ) && validateHidden !== true && isFieldHidden( field ) ) { return true; }\n\n\t\t// Bail if field doesn't need validation\n\t\tif ( ! needsValidation( field, formRow, validationEvent ) ) { return true; }\n\n\t\t// Execute validate field for all applicable validation types\n\t\tvar validationTypeNames = Object.getOwnPropertyNames( _validationTypes );\n\t\tfor ( var i = 0; i < validationTypeNames.length; i++) {\n\t\t\tvar validationTypeName = validationTypeNames[i];\n\t\t\tvar validationType = _validationTypes[ validationTypeName ];\n\t\t\tif ( validationType.needsValidation( field, formRow, validationEvent ) ) {\n\t\t\t\tvalidationResults[ validationTypeName ] = validationType.validate( field, formRow, validationEvent );\n\t\t\t}\n\t\t}\n\n\t\t// TODO: Maybe trigger validation of related fields (ie zip > State, Country)\n\n\t\t// Process results\n\t\treturn processValidationResults( field, formRow, validationResults );\n\t};\n\n\n\n\t/**\n\t * Trigger validation in all fields inside the container.\n\t * @param {Element} container Element to look for fields in, if not passed consider the checkout form as container.\n\t * @return {Boolean} True if all fields are valid.\n\t */\n\t_publicMethods.validateAllFields = function( container, validateHidden ) {\n\t\tif ( ! container ) { container = document.querySelector( _settings.formSelector ) }\n\n\t\tvar all_valid = true;\n\t\tvar fields = container.querySelectorAll( _settings.validateFieldsSelector );\n\n\t\tfor ( var i = 0; i < fields.length; i++ ) {\n\t\t\tif ( ! _publicMethods.validateField( fields[i], 'validate-all', validateHidden ) ) {\n\t\t\t\tall_valid = false;\n\t\t\t}\n\t\t}\n\n\t\treturn all_valid;\n\t};\n\n\n\n\t/**\n\t * Register a new validation type.\n\t *\n\t * @param String validationType A `snake_case` string representing the type of validation. Used as the validation type property on the `_validationTypes` object.\n\t * @param String invalidClass CSS class to be used on the `form-row` related to the field when the validation fails.\n\t * @param Function fnNeedsValidation A function to check if the field needs validation, should return `true` when the field needs validation.\n\t * @param Function fnValidate A function to validate the form field, should accept 2 parameters being `field` and `formRow`, both expected to be an HTMLElement.\n\t *\n\t * @return Boolean `true` when the registration of the validation type has been successful, `false` otherwise.\n\t */\n\t_publicMethods.registerValidationType = function( validationType, invalidClass, fnNeedsValidation, fnValidate ) {\n\t\t// Bail if _validationTypes not initialized\n\t\tif ( ! _validationTypes ) { return false; }\n\n\t\t// Bail if validationType or invalidClass not a string\n\t\tif ( typeof validationType !== 'string' || typeof invalidClass !== 'string' ) { return false; }\n\n\t\t// Bail if fnNeedsValidation or fnValidate are not functions\n\t\tif ( ! ( fnNeedsValidation instanceof Function ) || ! ( fnValidate instanceof Function ) ) { return false; }\n\t\t\n\t\t// Bail if validation type already registered\n\t\tif ( _validationTypes.hasOwnProperty( validationType ) ) {\n\t\t\tconsole.log( 'Validation type \"' + validationType + '\" already registered.' );\n\t\t\treturn false;\n\t\t}\n\n\t\t// Register validation type\n\t\t_validationTypes[ validationType ] = {\n\t\t\tinvalidClass: invalidClass,\n\t\t\tneedsValidation: fnNeedsValidation,\n\t\t\tvalidate: fnValidate,\n\t\t}\n\n\t\treturn true;\n\t}\n\n\n\n\t/**\n\t * Return the registered validation types.\n\t *\n\t * @return Object Object with the registered validation types as properties.\n\t */\n\t_publicMethods.getValidationTypes = function() {\n\t\treturn _validationTypes;\n\t}\n\n\t\n\n\t/**\n\t * Initialize component and set related handlers.\n\t */\n\t_publicMethods.init = function( options ) {\n\t\tif ( _hasInitialized ) return;\n\n\t\t// Merge settings\n\t\t_settings = FCUtils.extendObject( _settings, options );\n\n\t\t// Register validation types\n\t\tregisterValidationTypes();\n\n\t\tif ( _hasJQuery ) {\n\t\t\t$( _settings.formSelector ).on( 'input validate change', _settings.validateFieldsSelector, handleValidateEvent );\n\t\t\t\n\t\t\t// Run on checkout or cart changes\n\t\t\t$( document ).on( 'load_ajax_content_done', _publicMethods.init );\n\t\t\t$( document ).on( 'country_to_state_changed', maybeClearStateFields );\n\t\t}\n\n\t\t// Add body class\n\t\tdocument.body.classList.add( _settings.bodyClass );\n\n\t\t_hasInitialized = true;\n\t};\n\n\n\t\n\t//\n\t// Public APIs\n\t//\n\treturn _publicMethods;\n\n});\n"],"names":["root","factory","define","amd","exports","module","CheckoutValidation","global","this","window","isAlwaysValidate","field","_settings","alwaysValidateFieldsSelector","matches","isRequiredField","formRow","validationEvent","typeRequiredSelector","validateRequired","_publicMethods","hasValue","valid","message","validationMessages","required","isEmailField","typeEmailSelector","validateEmail","RegExp","test","value","email","isConfirmationField","querySelector","typeConfirmationSelector","validateConfirmation","confirmWith","form","closest","getAttribute","confirmation","isShippingMethodField","typeShippingMethodSelector","validateShippingMethod","processValidationResults","validationResults","validationResultsNames","Object","getOwnPropertyNames","i","length","validationTypeName","validationType","_validationTypes","result","invalidClass","classList","remove","messageElements","querySelectorAll","parentNode","removeChild","element","referenceNode","inputWrapperSelector","referenceNodeSelector","parent","isSelect2Field","newReference","document","createElement","className","innerText","insertBefore","nextSibling","add","toggle","validClass","maybeClearStateFields","event","country","wrapper","_hasJQuery","$","toArray","forEach","wrapperItem","Array","from","clearValidationCountryChangedSelector","formRowSelector","clearValidationResults","handleValidateEvent","e","target","validateField","type","jQuery","_hasInitialized","bodyClass","formSelector","validateFieldsSelector","select2Selector","options","selectedIndex","validationTypeKeys","keys","validateHidden","offsetParent","validationTypeNames","needsValidation","validate","validateAllFields","container","all_valid","fields","registerValidationType","fnNeedsValidation","fnValidate","Function","hasOwnProperty","console","log","getValidationTypes","init","FCUtils","extendObject","on","body"],"mappings":"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"}