2026-03-18 22:36:12 +00:00

983 lines
31 KiB
JavaScript

/*!
* jQuery bValidator plugin
*
* http://code.google.com/p/bvalidator/
*
* Copyright (c) 2012 Bojan Mauser
*
* Joomla! 2.5 Ajax Mod by Jaroslaw Paluch, SoftDeco, (c) 2013
*
* Released under the MIT license
* http://www.opensource.org/licenses/mit-license.php
*
* $Id: jquery.bvalidator.js 101 2012-09-30 23:51:36Z bmauser $
*/
(function($){
// constructor
$.fn.bValidator = function(overrideOptions, instanceName){
return this.each(function(){
new bValidator($(this), overrideOptions, instanceName);
});
};
// bValidator class
bValidator = function(mainElement, overrideOptions, instanceName){
// default options
var options = {
singleError: false, // validate all inputs at once
offset: {x:-23, y:-4}, // offset position for error message tooltip
position: {x:'right', y:'top'}, // error message placement x:left|center|right y:top|center|bottom
template: '<div class="{errMsgClass}">{message}<em></em></div>', // template for error message
templateCloseIcon: '<div style="display:table"><div style="display:table-cell">{message}</div><div style="display:table-cell"><div class="{closeIconClass}">x</div></div></div>', // template for error message container when showCloseIcon option is true
showCloseIcon: true, // put close icon on error message
showErrMsgSpeed: 'normal', // message's fade-in speed 'fast', 'normal', 'slow' or number of milliseconds
scrollToError: true, // scroll to first error
// css class names
classNamePrefix: 'bvalidator_', // prefix for css class names
closeIconClass: 'close_icon', // close error message icon class
errMsgClass: 'errmsg', // error message class
errorClass: 'invalid', // input field class name in case of validation error
validClass: '', // input field class name in case of valid value
lang: 'en', // default language for error messages
errorMessageAttr: 'data-bvalidator-msg',// name of the attribute for overridden error message
validateActionsAttr: 'data-bvalidator', // name of the attribute which stores info what validation actions to do
forceValidAttr: 'data-bvalidator-forcevalid', // name of the attribute which which makes validator to act like the field is valid
modifyActionsAttr: 'data-bvalidator-modifier',
paramsDelimiter: ':', // delimiter for validator action options inside []
actionsDelimiter: ',', // delimiter for validator actions
// when to validate
validateOn: null, // null, 'change', 'blur', 'keyup'
errorValidateOn: 'keyup', // null, 'change', 'blur', 'keyup'
// callback functions
onBeforeValidate: null,
onAfterValidate: null,
onValidateFail: null,
onValidateSuccess: null,
onBeforeElementValidation: null,
onAfterElementValidation: null,
onBeforeAllValidations: null,
onAfterAllValidations: null,
validateOnSubmit: true, // should validation occur on form submit if validator is bind to a form
stopSubmitPropagation: true, // should submit event be stopped on error if validator is bind to a form
noMsgIfExistsForInstance: [],
validateTillInvalid: false,
autoModifiers: {
'digit': ['trim'],
'number': ['trim'],
'email': ['trim'],
'url': ['trim'],
'date': ['trim'],
'ip4': ['trim'],
'ip6': ['trim']
},
ajaxAnswerValid: 'ok',
ajaxDelay: 300,
ajaxOptions: {cache: false},
ajaxParamName: 'bValue',
// default messages
errorMessages: {
en: {
'default': 'Please correct this value.',
'equalto': 'Please enter the same value again.',
'differs': 'Please enter a different value.',
'minlength': 'The length must be at least {0} characters',
'maxlength': 'The length must be at max {0} characters',
'rangelength':'The length must be between {0} and {1}',
'min': 'Please enter a number greater than or equal to {0}.',
'max': 'Please enter a number less than or equal to {0}.',
'between': 'Please enter a number between {0} and {1}.',
'required': 'This field is required.',
'alpha': 'Please enter alphabetic characters only.',
'alphanum': 'Please enter alphanumeric characters only.',
'digit': 'Please enter only digits.',
'number': 'Please enter a valid number.',
'email': 'Please enter a valid email address.',
'image': 'This field should only contain image types',
'url': 'Please enter a valid URL.',
'ip4': 'Please enter a valid IPv4 address.',
'ip6': 'Please enter a valid IPv6 address.',
'date': 'Please enter a valid date in format {0}.'
}
}
},
_ajaxValidation = function(element, instanceName, ajaxUrl, sync, option, task){
var ajax_data = element.data("ajaxData.bV" + instanceName);
if(!ajax_data){
ajax_data = {};
element.data("ajaxData.bV" + instanceName, ajax_data);
}
else{
clearTimeout(ajax_data.timeOut);
}
// value to validate
ajax_data.val = element.val();
// do not do ajax if value is already validated
if(ajax_data.lastValidated === ajax_data.val)
return validator.ajax(ajax_data.lastResponse);
var ajaxOptions = $.extend({}, options.ajaxOptions);
if(typeof ajaxOptions.data != 'object')
ajaxOptions.data = {}
ajaxOptions.url = ajaxUrl;
ajaxOptions.type = 'POST';
if(sync){
var ret = false;
ajaxOptions.async = false;
ajaxOptions.data[options.ajaxParamName] = ajax_data.val;
if (option != undefined) {
ajaxOptions.data["option"] = option;
}
if (task != undefined) {
ajaxOptions.data["task"] = task;
}
$.ajax(ajaxOptions).done(function(ajaxResponse){
ajax_data.lastValidated = ajax_data.val;
ajax_data.lastResponse = ajaxResponse;
ret = validator.ajax(ajaxResponse)
});
return ret;
}
else{
ajax_data.timeOut = setTimeout(function() {
var val = element.val();
// only check if the value has not changed
if(ajax_data.val == val){
ajaxOptions.async = true;
ajaxOptions.data[options.ajaxParamName] = val;
if (option != undefined) {
ajaxOptions.data["option"] = option;
}
if (task != undefined) {
ajaxOptions.data["task"] = task;
}
$.ajax(ajaxOptions).done(function(ajaxResponse){
ajax_data.lastValidated = val;
ajax_data.lastResponse = ajaxResponse;
instance.validate(false, element, undefined, ajaxResponse)
});
}
}, options.ajaxDelay);
}
return;
},
// returns all inputs
_getElementsForValidation = function(element){
// skip hidden and input fields witch we do not want to validate
return element.is(':input') ? element : element.find(':input[' + options.validateActionsAttr + '], :input[' + options.modifyActionsAttr + ']').not(":button, :image, :reset, :submit, :hidden, :disabled");
},
// binds validateOn event
_bindValidateOn = function(elements){
elements.bind(options.validateOn + '.bV' + instanceName, {'bVInstance': instance}, function(event){
event.data.bVInstance.validate(false, $(this));
});
},
// checks does message from validator instance exists on element
_isMsgFromInstanceExists = function(element, instance_names){
for(var i=0; i<instance_names.length; i++){
if(element.data("errMsg.bV" + instance_names[i]))
return true;
}
return false;
},
// displays message
_showMsg = function(element, messages){
// if message already exists remove it from DOM
_removeMsg(element);
msg_container = $('<div class="bVErrMsgContainer"></div>').css('position','absolute');
element.data("errMsg.bV" + instanceName, msg_container);
msg_container.insertAfter(element);
var messagesHtml = '';
for(var i=0; i<messages.length; i++)
messagesHtml += '<div>' + messages[i] + '</div>\n';
if(options.showCloseIcon)
messagesHtml = options.templateCloseIcon.replace('{message}', messagesHtml).replace('{closeIconClass}', options.classNamePrefix+options.closeIconClass);
// make tooltip from template
var tooltip = $(options.template.replace('{errMsgClass}', options.classNamePrefix+options.errMsgClass).replace('{message}', messagesHtml));
tooltip.appendTo(msg_container);
// bind close tootlip function
tooltip.find('.' + options.classNamePrefix+options.closeIconClass).click(function(e){
e.preventDefault();
$(this).closest('.'+ options.classNamePrefix+options.errMsgClass).css('visibility', 'hidden');
});
var pos = _getErrMsgPosition(element, tooltip);
tooltip.css({visibility: 'visible', position: 'absolute', top: pos.top, left: pos.left}).fadeIn(options.showErrMsgSpeed);
if(options.scrollToError){
// get most top tolltip
var tot = tooltip.offset().top;
if(scroll_to === null || tot < scroll_to)
scroll_to = tot;
}
},
// removes message from DOM
_removeMsg = function(element){
var existingMsg = element.data("errMsg.bV" + instanceName)
if(existingMsg){
existingMsg.remove();
element.data("errMsg.bV" + instanceName, null);
}
},
// calculates message position
_getErrMsgPosition = function(input, tooltip){
var tooltipContainer = input.data("errMsg.bV" + instanceName),
top = - ((tooltipContainer.offset().top - input.offset().top) + tooltip.outerHeight() - options.offset.y),
left = (input.offset().left + input.outerWidth()) - tooltipContainer.offset().left + options.offset.x,
x = options.position.x,
y = options.position.y;
// adjust Y
if(y == 'center' || y == 'bottom'){
var height = tooltip.outerHeight() + input.outerHeight();
if (y == 'center') {top += height / 2;}
if (y == 'bottom') {top += height;}
}
// adjust X
if(x == 'center' || x == 'left'){
var width = input.outerWidth();
if (x == 'center') {left -= width / 2;}
if (x == 'left') {left -= width;}
}
return {top: top, left: left};
},
// calls callback function
_callBack = function(type, param1, param2, param3){
if($.isFunction(options[type])){
return options[type](param1, param2, param3);
}
},
// returns checkboxes in a group
_chkboxGroup = function(chkbox){
var name = chkbox.attr('name');
if(name && /^[^\[\]]+\[.*\]$/.test(name)){
return $('input:checkbox').filter(function(){
var r = new RegExp(name.match(/^[^\[\]]+/)[0] + '\\[.*\\]$');
return this.name.match(r);
});
}
return chkbox;
},
// gets element value
_getValue = function(element){
var ret = {};
// checkbox
if(element.is('input:checkbox')){
ret['value'] = element.attr('name') ? ret['selectedInGroup'] = _chkboxGroup(element).filter(':checked').length : element.attr('checked');
}
else if(element.is('input:radio')){
ret['value'] = element.attr('name') ? ret['value'] = $('input:radio[name="' + element.attr('name') + '"]:checked').length : element.val();
}
else if(element.is('select')){
ret['selectedInGroup'] = $("option:selected", element).length;
ret['value'] = element.val();
}
else if(element.is(':input')){
ret['value'] = element.val();
}
return ret;
},
// parses bValidator attributes
_parseAttr = function(attrVal){
// value of validateActionsAttr input attribute
var action_str = $.trim(attrVal).replace(new RegExp('\\s*\\' + options.actionsDelimiter + '\\s*', 'g'), options.actionsDelimiter);
if(!action_str)
return null;
return action_str.split(options.actionsDelimiter);
},
// parses validator action and parameters
_parseAction = function(actionStr){
var ap = $.trim(actionStr).match(/^(.*?)\[(.*?)\]/);
if(ap && ap.length == 3){
return {
name: ap[1],
params: ap[2].split(options.paramsDelimiter)
}
}
else{
return {
name: actionStr,
params:[]
}
}
},
// applys modifier
_applyModifier = function(action, el){
var oldVal, newVal = _callModifier(action, el);
if(typeof newVal !== 'undefined'){
oldVal = $(el).val();
if(oldVal != newVal)
$(el).val(newVal);
}
},
// calls modifier
_callModifier = function(action, el){
var apply_params = [$(el).val()].concat(action.params);
if(typeof modifier[action.name] == 'function')
return modifier[action.name].apply(el, apply_params);
else if(typeof window[action.name] == 'function')
return window[action.name].apply(el, apply_params);
else if(window.console.warn)
window.console.warn('[bValidator] unknown modifier: ' + action.name);
},
// calls validator
_callValidator = function(action, el, value){
if(typeof validator[action.name] == 'function'){
return validator[action.name].apply(el, [value].concat(action.params)); // add input value to beginning of action.params
}
// call custom user defined function
if(typeof window[action.name] == 'function'){
return window[action.name].apply(el, [value.value].concat(action.params));
}
if(window.console.warn)
window.console.warn('[bValidator] unknown validator: ' + action.name);
},
// object with validator actions
validator = {
equalto: function(v, elementId){
return v.value == $('#' + elementId).val();
},
differs: function(v, elementId){
return v.value != $('#' + elementId).val();
},
minlength: function(v, minlength){
return (v.value.length >= parseInt(minlength))
},
maxlength: function(v, maxlength){
return (v.value.length <= parseInt(maxlength))
},
rangelength: function(v, minlength, maxlength){
return (v.value.length >= parseInt(minlength) && v.value.length <= parseInt(maxlength))
},
min: function(v, min){
if(v.selectedInGroup)
return v.selectedInGroup >= parseFloat(min)
else{
if(!validator.number(v))
return false;
return (parseFloat(v.value) >= parseFloat(min))
}
},
max: function(v, max){
if(v.selectedInGroup)
return v.selectedInGroup <= parseFloat(max)
else{
if(!validator.number(v))
return false;
return (parseFloat(v.value) <= parseFloat(max))
}
},
between: function(v, min, max){
if(v.selectedInGroup)
return (v.selectedInGroup >= parseFloat(min) && v.selectedInGroup <= parseFloat(max))
if(!validator.number(v))
return false;
var va = parseFloat(v.value);
return (va >= parseFloat(min) && va <= parseFloat(max))
},
required: function(v){
if(!v.value || !$.trim(v.value))
return false
return true
},
alpha: function(v){
return validator.regex(v, /^[a-z ._\-]+$/i);
},
alphanum: function(v){
return validator.regex(v, /^[a-z\d ._\-]+$/i);
},
digit: function(v){
return validator.regex(v, /^\d+$/);
},
number: function(v){
return validator.regex(v, /^[-+]?\d+(\.\d+)?$/);
},
email: function(v){
return validator.regex(v, /^([a-zA-Z\d_\.\-\+%])+\@(([a-zA-Z\d\-])+\.)+([a-zA-Z\d]{2,4})+$/);
},
image: function(v){
return validator.regex(v, /\.(jpg|jpeg|png|gif|bmp)$/i);
},
url: function(v){
return validator.regex(v, /^\b(https?|ftp):\/\/([-A-Z0-9.]+)(\/[-A-Z0-9+&@#\/%=~_|!:,.;]*)?(\?[A-Z0-9+&@#\/%=~_|!:,.;]*)?$/i);
},
regex: function(v, regex, mod){
if(typeof regex === "string")
regex = new RegExp(regex, mod);
return regex.test(v.value);
},
ip4: function(v){
return validator.regex(v, /^(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)$/);
},
ip6: function(v){
return validator.regex(v, /^(?:(?:(?:[A-F\d]{1,4}:){5}[A-F\d]{1,4}|(?:[A-F\d]{1,4}:){4}:[A-F\d]{1,4}|(?:[A-F\d]{1,4}:){3}(?::[A-F\d]{1,4}){1,2}|(?:[A-F\d]{1,4}:){2}(?::[A-F\d]{1,4}){1,3}|[A-F\d]{1,4}:(?::[A-F\d]{1,4}){1,4}|(?:[A-F\d]{1,4}:){1,5}|:(?::[A-F\d]{1,4}){1,5}|:):(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\.){3}(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)|(?:[A-F\d]{1,4}:){7}[A-F\d]{1,4}|(?:[A-F\d]{1,4}:){6}:[A-F\d]{1,4}|(?:[A-F\d]{1,4}:){5}(?::[A-F\d]{1,4}){1,2}|(?:[A-F\d]{1,4}:){4}(?::[A-F\d]{1,4}){1,3}|(?:[A-F\d]{1,4}:){3}(?::[A-F\d]{1,4}){1,4}|(?:[A-F\d]{1,4}:){2}(?::[A-F\d]{1,4}){1,5}|[A-F\d]{1,4}:(?::[A-F\d]{1,4}){1,6}|(?:[A-F\d]{1,4}:){1,7}:|:(?::[A-F\d]{1,4}){1,7})$/i);
},
date: function(v, format){ // format can be any combination of mm,dd,yyyy with separator between. Example: 'mm.dd.yyyy' or 'yyyy-mm-dd'
if(v.value.length == 10 && format.length == 10){
var s = format.match(/[^mdy]+/g);
if(s.length == 2 && s[0].length == 1 && s[0] == s[1]){
var d = v.value.split(s[0]),
f = format.split(s[0]);
for(var i=0; i<3; i++){
if(f[i] == 'dd') var day = d[i];
else if(f[i] == 'mm') var month = d[i];
else if(f[i] == 'yyyy') var year = d[i];
}
var dobj = new Date(year, month-1, day)
if ((dobj.getMonth()+1!=month) || (dobj.getDate()!=day) || (dobj.getFullYear()!=year))
return false
return true
}
}
return false;
},
extension: function(){
var v = arguments[0],
r = '';
if(!arguments[1])
return false
for(var i=1; i<arguments.length; i++){
r += arguments[i];
if(i != arguments.length-1)
r += '|';
}
return validator.regex(v, '\\.(' + r + ')$', 'i');
},
ajax: function(ajaxResponse){
if(ajaxResponse == options.ajaxAnswerValid)
return true;
return false;
}
},
// object with modifiers
modifier = {
trim: function(v){
return $.trim(v);
}
},
// validator instance, scroll position flag
instance = this, scroll_to;
// global options
if(window['bValidatorOptions'])
$.extend(true, options, window['bValidatorOptions']);
// passed options
if(overrideOptions)
$.extend(true, options, overrideOptions);
// object with all validator instances
var allInstances = mainElement.data("bValidators");
if(!allInstances){
allInstances = {};
mainElement.data("bValidators", allInstances);
}
// if there is already first instance
if(mainElement.data("bValidator")){
if(!instanceName)
return mainElement.data("bValidator"); // return existing instance
if(allInstances[instanceName])
return allInstances[instanceName];
}
else{
if(!instanceName)
instanceName = 'first';
mainElement.data("bValidator", this);
}
allInstances[instanceName] = this;
// if bind to a form
if(mainElement.is('form')){
// bind validation on form submit
if(options.validateOnSubmit){
mainElement.bind("submit.bV" + instanceName, function(event){
if(instance.validate(false, undefined, 1))
return true;
else if(options.stopSubmitPropagation){
event.stopImmediatePropagation();
return false;
}
});
}
// bind reset on form reset
mainElement.bind("reset.bV" + instanceName, function(){
instance.reset();
});
}
// bind validateOn event
if(options.validateOn)
_bindValidateOn(_getElementsForValidation(mainElement));
// API functions:
// validation function
this.validate = function(doNotshowMessages, elementsOverride, forceAjaxSync, ajaxResponse, onlyIsValidCheck){
// return value, elements to validate
var ret = true,
elementsl = elementsOverride ? elementsOverride : _getElementsForValidation(mainElement);
scroll_to = null;
if(typeof ajaxResponse !== 'undefined' || _callBack('onBeforeAllValidations', elementsl) !== false){
// validate each element
elementsl.each(function(){
var actions_exp = _parseAttr($(this).attr(options.validateActionsAttr)), // all validation actions
modifiers_exp = _parseAttr($(this).attr(options.modifyActionsAttr)), // all modifier actions
k = -1, action_data = [], action, is_valid = 0;
// call modifiers
if(modifiers_exp){
for(var i=0; i<modifiers_exp.length; i++){
action = _parseAction(modifiers_exp[i]);
if(!action.name)
continue;
// call modifier
_applyModifier(action, this);
}
}
// call auto modifiers and prepare validation actions
if(actions_exp){
for(var i=0; i<actions_exp.length; i++){
action = _parseAction(actions_exp[i]);
if(!action.name)
continue;
// auto modifiers
if(options.autoModifiers && options.autoModifiers[action.name]){
for(var h=0; h<options.autoModifiers[action.name].length; h++)
_applyModifier(_parseAction(options.autoModifiers[action.name][h]), this);
}
if(action.name == 'required')
var flagRequired = 1;
else if(action.name == 'ajax')
var flagAjax = 1;
if(action.name == 'valempty')
var flagValempty = 1;
else
action_data[++k] = action; // action objects, with name and params
}
}
else
return true; // no actions for validation
var inputValue = _getValue($(this)), // value of input field for validation;
errorMessages = [], validationResult;
// call async ajax validation and skip element
if(!forceAjaxSync && flagAjax && typeof ajaxResponse === 'undefined'){
var skipAjaxAction = 0;
// call all validators till ajax
for(var i=0; i<action_data.length; i++){
if(action_data[i].name == 'ajax')
break;
if(!_callValidator(action_data[i], this, inputValue)){
skipAjaxAction = 1;
break;
}
}
if(!skipAjaxAction){
ajaxResponse = _ajaxValidation($(this), instanceName, action_data[0].params[0], 0, action_data[0].params[1], action_data[0].params[2]);
if(typeof ajaxResponse === 'undefined'){
return true;
}
}
}
// do not show message if exists for instance specified by noMsgIfExistsForInstance option
if(options.noMsgIfExistsForInstance.length && _isMsgFromInstanceExists($(this), options.noMsgIfExistsForInstance))
doNotshowMessages = 1;
// if value is not required and is empty
if((!flagRequired && !flagValempty && !validator.required(inputValue)) || $(this).attr(options.forceValidAttr) == 'true')
is_valid = 1;
if(!is_valid){
// get message from attribute
var errMsg = $(this).attr(options.errorMessageAttr),
skip_messages = 0;
// mark field as validated
$(this).data('checked.bV' + instanceName, 1);
if(_callBack('onBeforeElementValidation', $(this)) !== false){
// for each validation action
for(var i=0; i<action_data.length; i++){
if(action_data[i].name == 'valempty')
continue;
if((options.validateTillInvalid || onlyIsValidCheck) && errorMessages.length){
break;
}
if(_callBack('onBeforeValidate', $(this), action_data[i].name) === false)
continue;
if(action_data[i].name == 'ajax'){
if(skipAjaxAction)
continue;
if(forceAjaxSync || typeof ajaxResponse === 'undefined'){
if(!errorMessages.length){
validationResult = _ajaxValidation($(this), instanceName, action_data[i].params[0], 1, action_data[i].params[1], action_data[i].params[2]);
}
else
validationResult = true; // skip ajax validation if value is already invalid
}
else{
validationResult = validator.ajax.apply(this, [ajaxResponse]);
}
}
else{
validationResult = _callValidator(action_data[i], this, inputValue);
}
if(_callBack('onAfterValidate', $(this), action_data[i].name, validationResult) === false)
continue;
// if validation failed
if(!validationResult){
// if messages needs to be shown
if(!doNotshowMessages){
if(!skip_messages){
// if there is no message from errorMessageAttr
if(!errMsg){
if (options.singleError && errorMessages.length){
skip_messages = 1;
errMsg = '';
}
else{
// lang set
if(options.errorMessages[options.lang] && options.errorMessages[options.lang][action_data[i].name])
errMsg = options.errorMessages[options.lang][action_data[i].name];
// lang en
else if(options.errorMessages.en[action_data[i].name])
errMsg = options.errorMessages.en[action_data[i].name];
else{
// action msg attribute
var tt = $(this).attr(options.errorMessageAttr + '-' + action_data[i].name);
if(tt)
errMsg = tt;
// lang set default msg
else if(options.errorMessages[options.lang] && options.errorMessages[options.lang]['default'])
errMsg = options.errorMessages[options.lang]['default'];
// lang en default msg
else
errMsg = options.errorMessages.en['default'];
}
}
}
else{
skip_messages = 1;
}
// replace values in braces
if(errMsg.indexOf('{')){
for(var j=0; j<action_data[i].params.length; j++)
errMsg = errMsg.replace(new RegExp("\\{" + j + "\\}", "g"), action_data[i].params[j]);
}
if(!(errorMessages.length && action_data[i].name == 'required'))
errorMessages[errorMessages.length] = errMsg;
errMsg = null;
}
}
else
errorMessages[errorMessages.length] = '';
ret = false;
_callBack('onValidateFail', $(this), action_data[i].name, errorMessages);
}
else{
_callBack('onValidateSuccess', $(this), action_data[i].name);
}
}
}
var onAfterElementValidation = _callBack('onAfterElementValidation', $(this), errorMessages);
}
// show messages and bind events
if(!doNotshowMessages && onAfterElementValidation !== false && $(this).data('checked.bV' + instanceName)){
var chk_rad = $(this).is('input:checkbox,input:radio') ? 1 : 0;
// if validation failed
if(errorMessages.length){
if(onAfterElementValidation !== 0)
_showMsg($(this), errorMessages)
if(!chk_rad){
$(this).removeClass(options.classNamePrefix+options.validClass);
if(options.errorClass)
$(this).addClass(options.classNamePrefix+options.errorClass);
}
// input validation event
if (options.errorValidateOn){
if(options.validateOn)
$(this).unbind(options.validateOn + '.bV' + instanceName);
var evt = chk_rad || $(this).is('select,input:file') ? 'change' : options.errorValidateOn;
if(chk_rad){
var group = $(this).is('input:checkbox') ? _chkboxGroup($(this)) : $('input:radio[name="' + $(this).attr('name') + '"]');
$(group).unbind('.bVerror' + instanceName);
$(group).bind('change.bVerror' + instanceName, {'bVInstance': instance, 'groupLeader': $(this)}, function(event){
event.data.bVInstance.validate(false, event.data.groupLeader);
});
}
else{
$(this).unbind('.bVerror' + instanceName);
$(this).bind(evt + '.bVerror' + instanceName, {'bVInstance': instance}, function(event){
event.data.bVInstance.validate(false, $(this));
});
}
}
}
else{
if(onAfterElementValidation !== 0)
_removeMsg($(this));
if(!chk_rad){
$(this).removeClass(options.classNamePrefix+options.errorClass);
if(options.validClass)
$(this).addClass(options.classNamePrefix+options.validClass);
}
if (options.validateOn){
$(this).unbind(options.validateOn + '.bV' + instanceName);
_bindValidateOn($(this));
}
$(this).data('checked.bV' + instanceName, 0);
}
}
if((options.singleError || onlyIsValidCheck) && ret === false)
return false;
});
}
_callBack('onAfterAllValidations', elementsl, ret);
// scroll to message
if(scroll_to && !elementsOverride && ($(window).scrollTop() > scroll_to || $(window).scrollTop()+$(window).height() < scroll_to)){
var ua = navigator.userAgent.toLowerCase();
$(ua.indexOf('chrome')>-1 || ua.indexOf('safari')>-1 ? 'body' : 'html').animate({scrollTop: scroll_to - 10}, {duration: 'slow'});
}
return ret;
}
// returns options object
this.getOptions = function(){
return options;
}
// returns validator object
this.getValidators = this.getActions = function(){
return validator;
}
// returns modifier object
this.getModifiers = function(){
return modifier;
}
// checks validity
this.isValid = function(elements){
return this.validate(true, elements, 1, undefined, true);
}
// deletes message
this.removeMsg = this.removeErrMsg = function(element){
_removeMsg(element);
}
// shows message
this.showMsg = function(element, message){
if(element.length){
if(typeof(message)=='string')
message = [message];
_showMsg(element, message);
}
}
// returns all inputs
this.getInputs = function(){
return _getElementsForValidation(mainElement);
}
// binds validateOn event
this.bindValidateOn = function(element){
_bindValidateOn(element);
}
// resets validation
this.reset = function(){
elements = _getElementsForValidation(mainElement);
if (options.validateOn)
_bindValidateOn(elements);
elements.each(function(){
_removeMsg($(this));
$(this).unbind('.bVerror' + instanceName);
$(this).removeClass(options.classNamePrefix+options.errorClass);
$(this).removeClass(options.classNamePrefix+options.validClass);
$(this).removeData('ajaxData.bV' + instanceName);
$(this).removeData('errMsg.bV' + instanceName);
$(this).removeData('checked.bV' + instanceName);
});
}
this.destroy = function(){
if (mainElement.is('form'))
mainElement.unbind('.bV' + instanceName);
this.reset();
mainElement.removeData("bValidator");
mainElement.removeData("bValidators");
}
}
})(jQuery);