{"version":3,"file":"index.min.js","sources":["index.ts"],"sourcesContent":[" /*\r\n * https://github.com/kraaden/unobtrusive-validation\r\n * Copyright (c) 2021 - Denys Krasnoshchok\r\n * MIT License\r\n */\r\n\r\ninterface IFormElement extends HTMLElement {\r\n value: string;\r\n type: string;\r\n}\r\n\r\n/**\r\n * List of handlers that will be executed after validation is finished for the submitted form.\r\n * You can use them to hide/show a spinner or do some additional work.\r\n */\r\nexport const validationHandlers: ((evt: Event, succeeded: boolean) => void)[] = [];\r\n\r\n/**\r\n * List of validators used by the library to validate form elements.\r\n * You can add you own validators when needed.\r\n */\r\nexport const validators: ((element: IFormElement) => boolean)[] = [];\r\n\r\nfunction getElementValue(element: IFormElement): string {\r\n return element.value;\r\n}\r\n\r\nfunction findContainer(element: HTMLElement): HTMLSpanElement | null {\r\n return document.querySelector(`span[data-valmsg-for='${element.getAttribute(\"name\")}']`) as HTMLSpanElement | null;\r\n}\r\n\r\nfunction isInt(value: string): boolean {\r\n return !isNaN(value as any) && Number.isInteger(parseFloat(value));\r\n}\r\n\r\nfunction clearError(element: HTMLElement) {\r\n const container = findContainer(element);\r\n if (container) {\r\n while (container.firstChild) {\r\n const child = container.firstChild;\r\n const parent = child.parentNode;\r\n if (parent) {\r\n parent.removeChild(child);\r\n }\r\n }\r\n container.classList.add(\"data-validation-valid\");\r\n }\r\n}\r\n\r\nfunction validateElement(element: IFormElement): boolean {\r\n let success = true;\r\n for (const validator of validators) {\r\n success = success && validator(element);\r\n }\r\n if (success) {\r\n clearError(element);\r\n }\r\n return success;\r\n}\r\n\r\nfunction showError(element: HTMLElement, message: string) {\r\n clearError(element);\r\n const container = findContainer(element);\r\n if (container) {\r\n container.textContent = message;\r\n container.classList.add(\"field-validation-error\");\r\n }\r\n}\r\n\r\nfunction requiredValidator(element: IFormElement): boolean {\r\n const message = element.getAttribute(\"data-val-required\");\r\n if (message) {\r\n const val = getElementValue(element).trim();\r\n if (!val) {\r\n showError(element, message);\r\n return false;\r\n }\r\n }\r\n return true;\r\n}\r\n\r\nfunction numberValidator(element: IFormElement): boolean {\r\n const message = element.getAttribute(\"data-val-number\");\r\n if (message) {\r\n const val = getElementValue(element).trim();\r\n if (!isInt(val)) {\r\n showError(element, message);\r\n return false;\r\n }\r\n }\r\n return true;\r\n}\r\n\r\nfunction lengthValidator(element: IFormElement): boolean {\r\n const errorMsg = element.getAttribute(\"data-val-length\");\r\n const minlen = element.getAttribute(\"data-val-length-min\");\r\n const maxlen = element.getAttribute(\"data-val-length-max\");\r\n const value = getElementValue(element);\r\n if (errorMsg && value) {\r\n if (maxlen) {\r\n const max = parseInt(maxlen, 10);\r\n if (value.length > max) {\r\n showError(element, errorMsg);\r\n return false;\r\n }\r\n }\r\n if (minlen) {\r\n const min = parseInt(minlen, 10);\r\n if (value.length < min) {\r\n showError(element, errorMsg);\r\n return false;\r\n }\r\n }\r\n }\r\n return true;\r\n}\r\n\r\nfunction regexValidator(element: IFormElement): boolean {\r\n const errorMsg = element.getAttribute(\"data-val-regex\");\r\n const regexPattern = element.getAttribute(\"data-val-regex-pattern\");\r\n const value = getElementValue(element);\r\n if (errorMsg && regexPattern && value) {\r\n if (!value.match(`^${regexPattern}$`)) {\r\n showError(element, errorMsg);\r\n return false;\r\n }\r\n }\r\n return true;\r\n}\r\n\r\nfunction equalityValidator(element: IFormElement): boolean {\r\n const errorMsg = element.getAttribute(\"data-val-equalto\");\r\n const other = element.getAttribute(\"data-val-equalto-other\") || \"\";\r\n const name = other.replace(/[^0-9a-zA-Z_]/g, '');\r\n if (name) {\r\n const anotherField = document.querySelector(\"[name='\" + name + \"']\") as IFormElement;\r\n if (errorMsg && anotherField) {\r\n if (anotherField.value !== element.value) {\r\n showError(element, errorMsg);\r\n return false;\r\n }\r\n }\r\n }\r\n\r\n return true;\r\n}\r\n\r\nfunction rangeValidator(element: IFormElement): boolean {\r\n const errorMsg = element.getAttribute(\"data-val-range\");\r\n const minval = element.getAttribute(\"data-val-range-min\");\r\n const maxval = element.getAttribute(\"data-val-range-max\");\r\n const value = getElementValue(element);\r\n\r\n if (errorMsg && isInt(value)) {\r\n const number = parseInt(value, 10);\r\n if (minval) {\r\n const min = parseInt(minval, 10);\r\n if (number < min) {\r\n showError(element, errorMsg);\r\n return false;\r\n }\r\n }\r\n if (maxval) {\r\n const max = parseInt(maxval, 10);\r\n if (number > max) {\r\n showError(element, errorMsg);\r\n return false;\r\n }\r\n }\r\n }\r\n return true;\r\n}\r\n\r\nfunction addChangeListener(element: HTMLElement) {\r\n if (element.nodeName === \"TEXTAREA\") {\r\n element.addEventListener(\"keyup\", () => {\r\n validateElement(element as HTMLTextAreaElement);\r\n });\r\n return;\r\n }\r\n if (element.nodeName === \"INPUT\") {\r\n const input = element as HTMLInputElement;\r\n if (input.type === \"text\" || input.type === \"password\") {\r\n input.addEventListener(\"keyup\", () => {\r\n validateElement(input);\r\n });\r\n return;\r\n }\r\n }\r\n if (element.nodeName === \"SELECT\") {\r\n const select = element as HTMLSelectElement;\r\n select.addEventListener(\"change\", () => {\r\n validateElement(select);\r\n });\r\n }\r\n}\r\n\r\nfunction validateForm(form: HTMLFormElement): boolean {\r\n let valid = true;\r\n const submit = form.getAttribute(\"data-submitted\");\r\n \r\n if (!submit) {\r\n form.setAttribute(\"data-submitted\", \"true\");\r\n }\r\n\r\n var inputs = form.querySelectorAll(\"input, textarea, select\");\r\n\r\n [].forEach.call(inputs, function(input: HTMLInputElement) {\r\n if (input.type === \"hidden\") {\r\n return;\r\n }\r\n if (!submit) {\r\n addChangeListener(input);\r\n }\r\n const current = validateElement(input);\r\n valid = valid && current;\r\n });\r\n \r\n return valid;\r\n}\r\n\r\nvalidators.push(requiredValidator);\r\nvalidators.push(lengthValidator);\r\nvalidators.push(regexValidator);\r\nvalidators.push(rangeValidator);\r\nvalidators.push(numberValidator);\r\nvalidators.push(equalityValidator);\r\n\r\nfunction executeHandlers(evt: Event, succeeded: boolean) {\r\n for (let handler of validationHandlers) {\r\n handler(evt, succeeded);\r\n }\r\n}\r\n\r\nwindow.addEventListener('DOMContentLoaded', function() {\r\n var elements = document.querySelectorAll('form');\r\n\r\n [].forEach.call(elements, function(form: HTMLFormElement) {\r\n form.addEventListener(\"submit\", function(ev) {\r\n if (!validateForm(form)) {\r\n executeHandlers(ev, false);\r\n ev.preventDefault();\r\n return;\r\n }\r\n\r\n executeHandlers(ev, true);\r\n });\r\n });\r\n});"],"names":["validationHandlers","validators","getElementValue","element","value","findContainer","document","querySelector","getAttribute","isInt","isNaN","Number","isInteger","parseFloat","clearError","container","firstChild","child","parent_1","parentNode","removeChild","classList","add","validateElement","success","validators_1","_i","validator","showError","message","textContent","validateForm","form","valid","submit","setAttribute","inputs","querySelectorAll","forEach","call","input","type","nodeName","input_1","addEventListener","select_1","addChangeListener","current","executeHandlers","evt","succeeded","validationHandlers_1","handler","push","trim","errorMsg","minlen","maxlen","max","parseInt","length","min","regexPattern","match","minval","maxval","number","name","replace","anotherField","window","elements","ev","preventDefault"],"mappings":"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"}