/* http://plugins.jquery.com/validate */ ;(function(defaults, $, window, undefined) { var type = ['input:not([type]),input[type="color"],input[type="date"],input[type="datetime"],input[type="datetime-local"],input[type="email"],input[type="file"],input[type="hidden"],input[type="month"],input[type="number"],input[type="password"],input[type="range"],input[type="search"],input[type="tel"],input[type="text"],input[type="time"],input[type="url"],input[type="week"],textarea', 'select', 'input[type="checkbox"],input[type="radio"]'], // All field types allTypes = type.join(','), extend = {}, // Method to validate each fields validateField = function(event, options) { var // Field status status = { pattern : true, conditional : true, required : true }, // Current field field = $(this), // Current field value fieldValue = field.val() || '', // An index of extend fieldValidate = field.data('validate'), // A validation object (jQuery.fn.validateExtend) validation = fieldValidate !== undefined ? extend[fieldValidate] : {}, // One index or more separated for spaces to prepare the field value fieldPrepare = field.data('prepare') || validation.prepare, // A regular expression to validate field value fieldPattern = (field.data('pattern') || ($.type(validation.pattern) == 'regexp' ? validation.pattern : /(?:)/)), // Is case sensitive? (Boolean) fieldIgnoreCase = field.attr('data-ignore-case') || field.data('ignoreCase') || validation.ignoreCase, // A field mask fieldMask = field.data('mask') || validation.mask, // A index in the conditional object containing a function to validate the field value fieldConditional = field.data('conditional') || validation.conditional, // Is required? fieldRequired = field.data('required'), // The description element id fieldDescribedby = field.data('describedby') || validation.describedby, // An index of description object fieldDescription = field.data('description') || validation.description, // Trim spaces? fieldTrim = field.data('trim'), reTrue = /^(true|)$/i, reFalse = /^false$/i, // The description object fieldDescription = $.isPlainObject(fieldDescription) ? fieldDescription : (options.description[fieldDescription] || {}), name = 'validate'; fieldRequired = fieldRequired != '' ? (fieldRequired || !!validation.required) : true; fieldTrim = fieldTrim != '' ? (fieldTrim || !!validation.trim) : true; // Trim spaces? if(reTrue.test(fieldTrim)) { fieldValue = $.trim(fieldValue); } // The fieldPrepare is a function? if($.isFunction(fieldPrepare)) { // Updates the fieldValue variable fieldValue = String(fieldPrepare.call(field, fieldValue)); } else { // Is a function? if($.isFunction(options.prepare[fieldPrepare])) { // Updates the fieldValue variable fieldValue = String(options.prepare[fieldPrepare].call(field, fieldValue)); } } // Is not RegExp? if($.type(fieldPattern) != 'regexp') { fieldIgnoreCase = !reFalse.test(fieldIgnoreCase); // Converts to RegExp fieldPattern = fieldIgnoreCase ? RegExp(fieldPattern, 'i') : RegExp(fieldPattern); } // The conditional exists? if(fieldConditional != undefined) { // The fieldConditional is a function? if($.isFunction(fieldConditional)) { status.conditional = !!fieldConditional.call(field, fieldValue, options); } else { var // Splits the conditionals in an array conditionals = fieldConditional.split(/[\s\t]+/); // Each conditional for(var counter = 0, len = conditionals.length; counter < len; counter++) { if(options.conditional.hasOwnProperty(conditionals[counter]) && !options.conditional[conditionals[counter]].call(field, fieldValue, options)) { status.conditional = false; } } } } fieldRequired = reTrue.test(fieldRequired); // Is required? if(fieldRequired) { // Verifies the field type if(field.is(type[0] + ',' + type[1])) { // Is empty? if(!fieldValue.length > 0) { status.required = false; } } else if(field.is(type[2])) { if(field.is('[name]')) { // Is checked? if($('[name="' + field.prop('name') + '"]:checked').length == 0) { status.required = false; } } else { status.required = field.is(':checked'); } } } // Verifies the field type if(field.is(type[0])) { // Test the field value pattern if(fieldPattern.test(fieldValue)) { // If the event type is not equals to keyup if(event.type != 'keyup' && fieldMask !== undefined) { var matches = fieldValue.match(fieldPattern); // Each characters group for(var i = 0, len = matches.length; i < len; i++) { // Replace the groups fieldMask = fieldMask.replace(RegExp('\\$\\{' + i + '(?::`([^`]*)`)?\\}', 'g'), (matches[i] !== undefined ? matches[i] : '$1')); } fieldMask = fieldMask.replace(/\$\{\d+(?::`([^`]*)`)?\}/g, '$1'); // Test the field value pattern if(fieldPattern.test(fieldMask)) { // Update the field value field.val(fieldMask); } } } else { // If the field is required if(fieldRequired) { status.pattern = false; } else { if(fieldValue.length > 0) { status.pattern = false; } } } } var describedby = $('[id="' + fieldDescribedby +'"]'), log = fieldDescription.valid; if(describedby.length > 0 && event.type != 'keyup') { if(!status.required) { log = fieldDescription.required; } else if(!status.pattern) { log = fieldDescription.pattern; } else if(!status.conditional) { log = fieldDescription.conditional; } describedby.html(log || ''); } if(typeof(validation.each) == 'function') { validation.each.call(field, event, status, options); } // Call the eachField callback options.eachField.call(field, event, status, options); // If the field is valid if(status.required && status.pattern && status.conditional) { // If WAI-ARIA is enabled if(!!options.waiAria) { field.prop('aria-invalid', false); } if(typeof(validation.valid) == 'function') { validation.valid.call(field, event, status, options); } // Call the eachValidField callback options.eachValidField.call(field, event, status, options); } else { // If WAI-ARIA is enabled if(!!options.waiAria) { field.prop('aria-invalid', true); } if(typeof(validation.invalid) == 'function') { validation.invalid.call(field, event, status, options); } // Call the eachInvalidField callback options.eachInvalidField.call(field, event, status, options); } // Returns the field status return status; }; $.extend({ // Method to extends validations validateExtend : function(options) { return $.extend(extend, options); }, // Method to change the default properties of jQuery.fn.validate method validateSetup : function(options) { return $.extend(defaults, options); } }).fn.extend({ // Method to validate forms validate : function(options) { options = $.extend({}, defaults, options); return $(this).validateDestroy().each(function() { var form = $(this); // This is a form? if(form.is('form')) { form.data(name, { options : options }); var fields = form.find(allTypes), // Events namespace namespace = options.namespace; if(form.is('[id]')) { fields = fields.add('[form="' + form.prop('id') + '"]').filter(allTypes); } fields = fields.filter(options.filter); // If onKeyup is enabled if(!!options.onKeyup) { fields.filter(type[0]).on('keyup.' + namespace, function(event) { validateField.call(this, event, options); }); } // If onBlur is enabled if(!!options.onBlur) { fields.on('blur.' + namespace, function(event) { validateField.call(this, event, options); }); } // If onChange is enabled if(!!options.onChange) { fields.on('change.' + namespace, function(event) { validateField.call(this, event, options); }); } // If onSubmit is enabled if(!!options.onSubmit) { form.on('submit.' + namespace, function(event) { var formValid = true; fields.each(function() { var status = validateField.call(this, event, options); if(!status.pattern || !status.conditional || !status.required) { formValid = false; } }); // If form is valid if(formValid) { // Send form? if(!options.sendForm) { event.preventDefault(); } // Is a function? if($.isFunction(options.valid)) { options.valid.call(form, event, options); } } else { event.preventDefault(); event.stopImmediatePropagation(); // Is a function? if($.isFunction(options.invalid)) { options.invalid.call(form, event, options); } } }); } } }); }, // Method to destroy validations validateDestroy : function() { var form = $(this), dataValidate = form.data(name); // If this is a form if(form.is('form') && $.isPlainObject(dataValidate) && typeof(dataValidate.options.nameSpace) == 'string') { var fields = form.removeData(name).find(allTypes).add(form); if(form.is('[id]')) { fields = fields.add($('[form="' + form.prop('id') + '"]').filter(allTypes)); } fields.off('.' + dataValidate.options.nameSpace); } return form; } }); })({ // Send form if is valid? sendForm : true, // Use WAI-ARIA properties waiAria : true, // Validate on submit? onSubmit : true, // Validate on onKeyup? onKeyup : false, // Validate on onBlur? onBlur : false, // Validate on onChange? onChange : false, // Default namespace nameSpace : 'validate', // Conditional functions conditional : {}, // Prepare functions prepare : {}, // Fields descriptions description : {}, // Callback eachField : $.noop, // Callback eachInvalidField : $.noop, // Callback eachValidField : $.noop, // Callback invalid : $.noop, // Callback valid : $.noop, // A fielter to the fields filter : '*' }, jQuery, window);