{"version":3,"file":"../checkout-validation-208.min.js","sources":["checkout-validation-208.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\n\n\n\t/*!\n\t* Merge two or more objects together.\n\t* (c) 2017 Chris Ferdinandi, MIT License, https://gomakethings.com\n\t* @param {Boolean} deep If true, do a deep (or recursive) merge [optional]\n\t* @param {Object} objects The objects to merge together\n\t* @returns {Object} Merged values of defaults and options\n\t*/\n\tvar extend = function () {\n\t\t// Variables\n\t\tvar extended = {};\n\t\tvar deep = false;\n\t\tvar i = 0;\n\n\t\t// Check if a deep merge\n\t\tif ( Object.prototype.toString.call( arguments[0] ) === '[object Boolean]' ) {\n\t\t\tdeep = arguments[0];\n\t\t\ti++;\n\t\t}\n\n\t\t// Merge the object into the extended object\n\t\tvar merge = function (obj) {\n\t\t\tfor (var prop in obj) {\n\t\t\t\tif (obj.hasOwnProperty(prop)) {\n\t\t\t\t\t// If property is an object, merge properties\n\t\t\t\t\tif (deep && Object.prototype.toString.call(obj[prop]) === '[object Object]') {\n\t\t\t\t\t\textended[prop] = extend(extended[prop], obj[prop]);\n\t\t\t\t\t} else {\n\t\t\t\t\t\textended[prop] = obj[prop];\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\t// Loop through each object and conduct a merge\n\t\tfor (; i < arguments.length; i++) {\n\t\t\tvar obj = arguments[i];\n\t\t\tmerge(obj);\n\t\t}\n\n\t\treturn extended;\n };\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 * @return {Boolean} True if required.\n\t */\n\tvar isRequiredField = function( field, formRow ) {\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 */\n\tvar validateRequired = function( field, formRow ) {\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 * @return {Boolean} True if is email field.\n\t */\n\tvar isEmailField = function( field, formRow ) {\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 */\n\tvar validateEmail = function( field, formRow ) {\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 * @return {Boolean} True if is a confimation field.\n\t */\n\tvar isConfirmationField = function( field, formRow ) {\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 */\n\tvar validateConfirmation = function( field, formRow ) {\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 form row is required.\n\t * @param {Field} field Field for validation.\n\t * @param {Element} formRow Form row element.\n\t * @return {Boolean} True if required.\n\t */\n\t var isShippingMethodField = function( field, formRow ) {\n\t\tif ( ! formRow.matches( _settings.typeShippingMethodSelector ) ) { 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 */\n\tvar validateShippingMethod = function( field, formRow ) {\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 * @return {Boolean} True if field needs any validation.\n\t */\n\tvar needsValidation = function( field, formRow ) {\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 ) ) {\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 messages for the current validation type\n\t\t\tremoveInlineMessage( field, formRow, invalidClass );\n\n\t\t\t// Toggle validation `invalidClass` according to validation `result`\n\t\t\tformRow.classList.toggle( _settings.invalidClass +'-'+ validationType.invalidClass, true !== result );\n\n\t\t\t// Maybe set field as invalid\n\t\t\tif ( true !== result ) {\n\t\t\t\tvalid = false;\n\t\t\t\taddInlineMessage( field, formRow, message, invalidClass );\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 );\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 {Boolean} True if field is valid.\n\t */\n\t_publicMethods.validateField = function( field, 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 ) ) { 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 ) ) {\n\t\t\t\tvalidationResults[ validationTypeName ] = validationType.validate( field, formRow );\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], 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 = extend( _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","extend","extended","deep","i","Object","prototype","toString","call","arguments","length","prop","obj","hasOwnProperty","isAlwaysValidate","field","_settings","alwaysValidateFieldsSelector","matches","isRequiredField","formRow","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","getOwnPropertyNames","validationTypeName","validationType","_validationTypes","result","invalidClass","messageElements","querySelectorAll","parentNode","removeChild","classList","toggle","element","referenceNode","inputWrapperSelector","referenceNodeSelector","parent","isSelect2Field","newReference","document","createElement","className","innerText","insertBefore","nextSibling","validClass","maybeClearStateFields","event","country","wrapper","_hasJQuery","$","toArray","forEach","wrapperItem","Array","from","clearValidationCountryChangedSelector","formRowSelector","clearValidationResults","handleValidateEvent","e","target","validateField","jQuery","_hasInitialized","bodyClass","formSelector","validateFieldsSelector","select2Selector","options","selectedIndex","validationTypeKeys","keys","type","remove","validateHidden","getFormRow","offsetParent","validationTypeNames","needsValidation","validate","validateAllFields","container","all_valid","fields","registerValidationType","fnNeedsValidation","fnValidate","Function","console","log","getValidationTypes","init","on","body","add"],"mappings":"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"}