UNPKG

myei-validatejs

Version:

A JavaScript plugin that makes easy to implement validations on a website

270 lines (221 loc) 9.21 kB
/** * Validate.js * * https://github.com/myei/validate.js */ var Validate = function (user_options) { var options = { type: 'all', group: '', required: true, warn: true, lang: {}, descriptions: true, animations: true, color: 'red', align: 'right', realTime: true, debug: false }, regs = { letters: /^[a-zA-Z]+$/, lettersSpaces: /^[A-Za-z ]+$/, numbers: /^[0-9]+$/, lettersNumbers: /^[a-zA-Z0-9]+$/, passwd: /^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[!@#._\-\$%\^&\*])(?=.{1,})/, ip: /^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$/, url: /^(https?:\/\/)+((([a-z\d]([a-z\d-]*[a-z\d])*)\.)+[a-z]{2,}|((\d{1,3}\.){3}\d{1,3}))(\:\d+)?(\/[-a-z\d%_.~+]*)*(\?[;&a-z\d%_.~+=-]*)?(\#[-a-z\d_]*)?$/ }, rules = { min: function (el, arg, doIt) { return doIt ? el.val().length >= arg : true; }, max: function (el, arg, doIt) { return doIt ? el.val().length <= arg : true; }, email: function (el, arg, doIt) { if (_this.nodeName === 'email' || doIt) { var text = el.val(), at = text.lastIndexOf('@'), dot = text.lastIndexOf('.'); return at > 0 && dot > at + 1 && text.length > dot + 2 && regs.letters.test(text.substr(dot + 1, text.length - 1)); } return true; }, pattern: function (el, arg, doIt) { return doIt ? RegExp(arg).test(el.val()) : true; }, checkbox: function (el) { return _this.nodeName === 'checkbox' ? checkboxRadio(el) : true; }, radio: function (el) { return _this.nodeName === 'radio' ? checkboxRadio(el) : true; }, default: function (el) { return !!el.val()[0]; } }, live = { alphabetic: function (e) { return regs.lettersSpaces.test(e.key) || defaultKeys.includes(e.key.toLowerCase()); }, numeric: function (e) { return regs.numbers.test(e.key) || defaultKeys.includes(e.key.toLowerCase()); }, alphanumeric: function (e) { return regs.lettersNumbers.test(e.key) || defaultKeys.includes(e.key.toLowerCase()); } }, custom = {} , lang = { min: 'La longitud de caracteres mínima para este campo es de: ', max: 'La longitud de caracteres máxima para este campo es de: ', numbers: 'Este campo solo permite números', letters: 'Este campo solo permite letras (sin espacios)', lettersSpaces: 'Este campo solo permite letras', lettersNumbers: 'Este campo permite letras y números (sin espacios)', text: 'Este campo es requerido y no puede estar vacío', password: 'Este campo es requerido y no puede estar vacío', passwd: 'Al menos una letra mayúscula <br> - Al menos una letra minúscula <br> - Al menos un carácter numérico <br> - Al menos un carácter especial (!@#._-$%^&*)', 'select-one': 'Debe seleccionar alguna opción de la lista', 'select-multiple': 'Debe seleccionar al menos una opción de la lista', email: 'Debe ser un email válido', textarea: 'Este campo es requerido y no puede estar vacío', hidden: 'Este campo es requerido y no puede estar vacío', checkbox: 'Este campo es requerido y no puede estar vacío', radio: 'Este campo es requerido y no puede estar vacío', file: 'Debe agregar al menos un archivo', ip: 'Esto no es una dirección ip valida', url: 'Esto no es una url correcta. <br> - ej: https://google.com', pattern: 'Esto no cumple con el patrón especificado: ' }, _this = this, selectors = { warn: 'validate-warn', description: 'validate-warn-description', styles: 'validate-styles', target: 'input,select,textarea' }, defaultKeys = ['tab', 'backspace', 'delete', 'enter', 'home', 'end', 'pageup', 'pagedown'], select2 = 's2'; var build = function (user_options) { try { options = Object.assign(options, user_options); selectors.target = options.type === 'group' ? '.' + options.group : selectors.target; if (options.required) selectors.target = selectors.target.split(',').map(function(t){return t + '[required]';}).join(','); setLang(options.lang); if (!jQuery('#' + selectors.styles).length) jQuery('<style id="' + selectors.styles + '">.' + selectors.warn + ' { border-color: ' + options.color + ' !important; } .' + selectors.description + ' { color: ' + options.color + ' !important; font-size: 11px; font-family: Roboto, sans-serif; letter-spacing: 1px; float: ' + (options.align) + '; }</style>').appendTo('head'); if (options.realTime) jQuery('body').on('keyup change', selectors.target, function() { handleField(this, true); }); } catch (e) { if (options.debug) console.error('validate.js: Excepción construyendo instancia con las opciones suministradas:', options, e.message); } }; var itsOk = function () { var status = true; try { jQuery(selectors.target).each(function(index, el) { if (!handleField(el)) status = false; }); } catch (e) { if (options.debug) console.error('validate.js: Excepción validando con el target especificado:', selectors.target, 'e:', e.message); } return status; }; var setLang = function (_lang) { if (typeof _lang != 'object' && options.debug) console.error('validate.js: options.lang debe ser JSON:', _lang); options.lang = Object.assign(lang, options.lang); }; var addWarn = function (el, show, live) { if (options.warn && show) { var _el = jQuery(el); (hasData(_el, select2) ? _el.next().children().children() : _el).addClass(selectors.warn); if (options.animations && !live) { var aux = parseInt(_el.css('margin-left')); (hasData(_el, select2) ? _el.next() : _el).animate({ marginLeft: (aux - 10) + 'px' }, 100) .animate({ marginLeft: (aux + 10) + 'px' }, 100) .animate({ marginLeft: (aux - 10) + 'px' }, 100) .animate({ marginLeft: (aux + 10) + 'px' }, 100) .animate({ marginLeft: aux + 'px' }, 100); } if (options.descriptions) addDescription(el); } }; var addDescription = function (el) { var msg = '', el = jQuery(el); if (this.errors.indexOf('default') != -1) this.errors.splice(this.errors.indexOf('default'), 1); this.errors.forEach(function (error) { msg += ' - ' + (el.data(error + '-msg') || options.lang[error] + (el.data(error) && el.data(error) !== '' ? el.data(error) : '')) + '<br />'; }); (hasData(el, select2) ? el.next() : el).after('<span class="' + selectors.description + '">' + (msg.length ? msg : ' - ' + (el.data('default-msg') || options.lang[this.nodeName])) + '</span>'); }; var field = function (el) { try { var jobs = Object.keys(regs).concat(Object.keys(rules)).concat(Object.keys(custom)); el = jQuery(el); if (hasData(el, 'optional') && !rules['default'](el)) return true; this.errors = jobs.filter(function (job) { var doIt = hasData(el, job); return job in rules ? !rules[job](el, el.data(job), doIt) : job in regs && doIt ? !regs[job].test(el.val()) : doIt ? !custom[job](el, el.data(job)) : false; }); } catch (e) { if (options.debug) console.error('validate.js: Excepción validando campo: ', el, ' e: ', e.message); } return this.errors.length === 0; }; var checkboxRadio = function (el) { if (!el.prop('name')) throw new Error('Los campos ckeckbox y radio requieren el uso de la propiedad name para poder validar correctamente.'); return jQuery(el.prop('nodeName').toLowerCase() + '[type=' + this.nodeName + '][name=' + el.prop('name') + ']').is(':checked'); }; var handleField = function (el, live) { this.nodeName = el.type; var status = field(el); clean(el); addWarn(el, !status, live); return status; }; var clean = function (el) { var el = jQuery(el); (hasData(el, select2) ? el.next().children().children() : el).removeClass(selectors.warn); if ((hasData(el, select2) ? el.next() : el).next().hasClass(selectors.description)) (hasData(el, select2) ? el.next() : el).next().remove(); }; var hasData = function (el, data) { return !!el.data(data) || el.data(data) === ''; }; var addLive = function (role, target) { target = typeof target === 'undefined' ? '.validate-' + role : '.' + target; jQuery('body').on('keydown keypress', target, live[role]); }; var addRule = function (name, callback, message) { if (name in rules) { console.warn('validate.js: La regla ' + name.toUpperCase() + ' ya existe y no puede sobreescribirla'); return; } if (!Array.from(arguments).every(function (arg) { return !!arg; })) { console.warn('validate.js: Para añadir reglas personalizadas debe especificar: name, callback, message'); return; } custom[name] = callback; lang[name] = message; }; build(user_options); return { addLive: function (role, target) { return addLive(role, target); }, addRule: function (name, callback, message) { addRule(name, callback, message); }, itsOk: function () { return itsOk(); }, reset: function () { document.querySelectorAll(selectors.target).forEach(function (e) { e.classList.remove(selectors.warn); }); document.querySelectorAll('.' + selectors.description).forEach(function (e) { e.parentNode.removeChild(e); }); } }; };