grgw_old_java/heatsupply2/WebContent/static/jquery-validation/1.14.0/jquery.validate.min.js

1448 lines
44 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*!
* jQuery Validation Plugin v1.14.0
*
* http://jqueryvalidation.org/
*
* Copyright (c) 2015 Jörn Zaefferer
* Released under the MIT license
*/
(function( factory ) {
if ( typeof define === "function" && define.amd ) {
define( ["jquery"], factory );
} else {
factory( jQuery );
}
}(function( $ ) {
$.extend($.fn, {
// http://jqueryvalidation.org/validate/
validate: function( options ) {
// if nothing is selected, return nothing; can't chain anyway
if ( !this.length ) {
if ( options && options.debug && window.console ) {
console.warn( "Nothing selected, can't validate, returning nothing." );
}
return;
}
// check if a validator for this form was already created
var validator = $.data( this[ 0 ], "validator" );
if ( validator ) {
return validator;
}
// Add novalidate tag if HTML5.
this.attr( "novalidate", "novalidate" );
validator = new $.validator( options, this[ 0 ] );
$.data( this[ 0 ], "validator", validator );
if ( validator.settings.onsubmit ) {
this.on( "click.validate", ":submit", function( event ) {
if ( validator.settings.submitHandler ) {
validator.submitButton = event.target;
}
// allow suppressing validation by adding a cancel class to the submit button
if ( $( this ).hasClass( "cancel" ) ) {
validator.cancelSubmit = true;
}
// allow suppressing validation by adding the html5 formnovalidate attribute to the submit button
if ( $( this ).attr( "formnovalidate" ) !== undefined ) {
validator.cancelSubmit = true;
}
});
// validate the form on submit
this.on( "submit.validate", function( event ) {
if ( validator.settings.debug ) {
// prevent form submit to be able to see console output
event.preventDefault();
}
function handle() {
var hidden, result;
if ( validator.settings.submitHandler ) {
if ( validator.submitButton ) {
// insert a hidden input as a replacement for the missing submit button
hidden = $( "<input type='hidden'/>" )
.attr( "name", validator.submitButton.name )
.val( $( validator.submitButton ).val() )
.appendTo( validator.currentForm );
}
result = validator.settings.submitHandler.call( validator, validator.currentForm, event );
if ( validator.submitButton ) {
// and clean up afterwards; thanks to no-block-scope, hidden can be referenced
hidden.remove();
}
if ( result !== undefined ) {
return result;
}
return false;
}
return true;
}
// prevent submit for invalid forms or custom submit handlers
if ( validator.cancelSubmit ) {
validator.cancelSubmit = false;
return handle();
}
if ( validator.form() ) {
if ( validator.pendingRequest ) {
validator.formSubmitted = true;
return false;
}
return handle();
} else {
validator.focusInvalid();
return false;
}
});
}
return validator;
},
// http://jqueryvalidation.org/valid/
valid: function() {
var valid, validator, errorList;
if ( $( this[ 0 ] ).is( "form" ) ) {
valid = this.validate().form();
} else {
errorList = [];
valid = true;
validator = $( this[ 0 ].form ).validate();
this.each( function() {
valid = validator.element( this ) && valid;
errorList = errorList.concat( validator.errorList );
});
validator.errorList = errorList;
}
return valid;
},
// http://jqueryvalidation.org/rules/
rules: function( command, argument ) {
var element = this[ 0 ],
settings, staticRules, existingRules, data, param, filtered;
if ( command ) {
settings = $.data( element.form, "validator" ).settings;
staticRules = settings.rules;
existingRules = $.validator.staticRules( element );
switch ( command ) {
case "add":
$.extend( existingRules, $.validator.normalizeRule( argument ) );
// remove messages from rules, but allow them to be set separately
delete existingRules.messages;
staticRules[ element.name ] = existingRules;
if ( argument.messages ) {
settings.messages[ element.name ] = $.extend( settings.messages[ element.name ], argument.messages );
}
break;
case "remove":
if ( !argument ) {
delete staticRules[ element.name ];
return existingRules;
}
filtered = {};
$.each( argument.split( /\s/ ), function( index, method ) {
filtered[ method ] = existingRules[ method ];
delete existingRules[ method ];
if ( method === "required" ) {
$( element ).removeAttr( "aria-required" );
}
});
return filtered;
}
}
data = $.validator.normalizeRules(
$.extend(
{},
$.validator.classRules( element ),
$.validator.attributeRules( element ),
$.validator.dataRules( element ),
$.validator.staticRules( element )
), element );
// make sure required is at front
if ( data.required ) {
param = data.required;
delete data.required;
data = $.extend( { required: param }, data );
$( element ).attr( "aria-required", "true" );
}
// make sure remote is at back
if ( data.remote ) {
param = data.remote;
delete data.remote;
data = $.extend( data, { remote: param });
}
return data;
}
});
// Custom selectors
$.extend( $.expr[ ":" ], {
// http://jqueryvalidation.org/blank-selector/
blank: function( a ) {
return !$.trim( "" + $( a ).val() );
},
// http://jqueryvalidation.org/filled-selector/
filled: function( a ) {
return !!$.trim( "" + $( a ).val() );
},
// http://jqueryvalidation.org/unchecked-selector/
unchecked: function( a ) {
return !$( a ).prop( "checked" );
}
});
// constructor for validator
$.validator = function( options, form ) {
this.settings = $.extend( true, {}, $.validator.defaults, options );
this.currentForm = form;
this.init();
};
// http://jqueryvalidation.org/jQuery.validator.format/
$.validator.format = function( source, params ) {
if ( arguments.length === 1 ) {
return function() {
var args = $.makeArray( arguments );
args.unshift( source );
return $.validator.format.apply( this, args );
};
}
if ( arguments.length > 2 && params.constructor !== Array ) {
params = $.makeArray( arguments ).slice( 1 );
}
if ( params.constructor !== Array ) {
params = [ params ];
}
$.each( params, function( i, n ) {
source = source.replace( new RegExp( "\\{" + i + "\\}", "g" ), function() {
return n;
});
});
return source;
};
$.extend( $.validator, {
defaults: {
messages: {},
groups: {},
rules: {},
errorClass: "error",
validClass: "valid",
errorElement: "label",
focusCleanup: false,
focusInvalid: true,
errorContainer: $( [] ),
errorLabelContainer: $( [] ),
onsubmit: true,
ignore: ":hidden",
ignoreTitle: false,
onfocusin: function( element ) {
this.lastActive = element;
// Hide error label and remove error class on focus if enabled
if ( this.settings.focusCleanup ) {
if ( this.settings.unhighlight ) {
this.settings.unhighlight.call( this, element, this.settings.errorClass, this.settings.validClass );
}
this.hideThese( this.errorsFor( element ) );
}
},
onfocusout: function( element ) {
if ( !this.checkable( element ) && ( element.name in this.submitted || !this.optional( element ) ) ) {
this.element( element );
}
},
onkeyup: function( element, event ) {
// Avoid revalidate the field when pressing one of the following keys
// Shift => 16
// Ctrl => 17
// Alt => 18
// Caps lock => 20
// End => 35
// Home => 36
// Left arrow => 37
// Up arrow => 38
// Right arrow => 39
// Down arrow => 40
// Insert => 45
// Num lock => 144
// AltGr key => 225
var excludedKeys = [
16, 17, 18, 20, 35, 36, 37,
38, 39, 40, 45, 144, 225
];
if ( event.which === 9 && this.elementValue( element ) === "" || $.inArray( event.keyCode, excludedKeys ) !== -1 ) {
return;
} else if ( element.name in this.submitted || element === this.lastElement ) {
this.element( element );
}
},
onclick: function( element ) {
// click on selects, radiobuttons and checkboxes
if ( element.name in this.submitted ) {
this.element( element );
// or option elements, check parent select in that case
} else if ( element.parentNode.name in this.submitted ) {
this.element( element.parentNode );
}
},
highlight: function( element, errorClass, validClass ) {
if ( element.type === "radio" ) {
this.findByName( element.name ).addClass( errorClass ).removeClass( validClass );
} else {
$( element ).addClass( errorClass ).removeClass( validClass );
}
},
unhighlight: function( element, errorClass, validClass ) {
if ( element.type === "radio" ) {
this.findByName( element.name ).removeClass( errorClass ).addClass( validClass );
} else {
$( element ).removeClass( errorClass ).addClass( validClass );
}
}
},
// http://jqueryvalidation.org/jQuery.validator.setDefaults/
setDefaults: function( settings ) {
$.extend( $.validator.defaults, settings );
},
messages: {
required: "This field is required.",
remote: "Please fix this field.",
email: "Please enter a valid email address.",
url: "Please enter a valid URL.",
date: "Please enter a valid date.",
dateISO: "Please enter a valid date ( ISO ).",
number: "Please enter a valid number.",
digits: "Please enter only digits.",
creditcard: "Please enter a valid credit card number.",
equalTo: "Please enter the same value again.",
maxlength: $.validator.format( "Please enter no more than {0} characters." ),
minlength: $.validator.format( "Please enter at least {0} characters." ),
rangelength: $.validator.format( "Please enter a value between {0} and {1} characters long." ),
range: $.validator.format( "Please enter a value between {0} and {1}." ),
max: $.validator.format( "Please enter a value less than or equal to {0}." ),
min: $.validator.format( "Please enter a value greater than or equal to {0}." )
},
autoCreateRanges: false,
prototype: {
init: function() {
this.labelContainer = $( this.settings.errorLabelContainer );
this.errorContext = this.labelContainer.length && this.labelContainer || $( this.currentForm );
this.containers = $( this.settings.errorContainer ).add( this.settings.errorLabelContainer );
this.submitted = {};
this.valueCache = {};
this.pendingRequest = 0;
this.pending = {};
this.invalid = {};
this.reset();
var groups = ( this.groups = {} ),
rules;
$.each( this.settings.groups, function( key, value ) {
if ( typeof value === "string" ) {
value = value.split( /\s/ );
}
$.each( value, function( index, name ) {
groups[ name ] = key;
});
});
rules = this.settings.rules;
$.each( rules, function( key, value ) {
rules[ key ] = $.validator.normalizeRule( value );
});
function delegate( event ) {
var validator = $.data( this.form, "validator" ),
eventType = "on" + event.type.replace( /^validate/, "" ),
settings = validator.settings;
if ( settings[ eventType ] && !$( this ).is( settings.ignore ) ) {
settings[ eventType ].call( validator, this, event );
}
}
$( this.currentForm )
.on( "focusin.validate focusout.validate keyup.validate",
":text, [type='password'], [type='file'], select, textarea, [type='number'], [type='search'], " +
"[type='tel'], [type='url'], [type='email'], [type='datetime'], [type='date'], [type='month'], " +
"[type='week'], [type='time'], [type='datetime-local'], [type='range'], [type='color'], " +
"[type='radio'], [type='checkbox']", delegate)
// Support: Chrome, oldIE
// "select" is provided as event.target when clicking a option
.on("click.validate", "select, option, [type='radio'], [type='checkbox']", delegate);
if ( this.settings.invalidHandler ) {
$( this.currentForm ).on( "invalid-form.validate", this.settings.invalidHandler );
}
// Add aria-required to any Static/Data/Class required fields before first validation
// Screen readers require this attribute to be present before the initial submission http://www.w3.org/TR/WCAG-TECHS/ARIA2.html
$( this.currentForm ).find( "[required], [data-rule-required], .required" ).attr( "aria-required", "true" );
},
// http://jqueryvalidation.org/Validator.form/
form: function() {
this.checkForm();
$.extend( this.submitted, this.errorMap );
this.invalid = $.extend({}, this.errorMap );
if ( !this.valid() ) {
$( this.currentForm ).triggerHandler( "invalid-form", [ this ]);
}
this.showErrors();
return this.valid();
},
checkForm: function() {
this.prepareForm();
for ( var i = 0, elements = ( this.currentElements = this.elements() ); elements[ i ]; i++ ) {
this.check( elements[ i ] );
}
return this.valid();
},
// http://jqueryvalidation.org/Validator.element/
element: function( element ) {
var cleanElement = this.clean( element ),
checkElement = this.validationTargetFor( cleanElement ),
result = true;
this.lastElement = checkElement;
if ( checkElement === undefined ) {
delete this.invalid[ cleanElement.name ];
} else {
this.prepareElement( checkElement );
this.currentElements = $( checkElement );
result = this.check( checkElement ) !== false;
if ( result ) {
delete this.invalid[ checkElement.name ];
} else {
this.invalid[ checkElement.name ] = true;
}
}
// Add aria-invalid status for screen readers
$( element ).attr( "aria-invalid", !result );
if ( !this.numberOfInvalids() ) {
// Hide error containers on last error
this.toHide = this.toHide.add( this.containers );
}
this.showErrors();
return result;
},
// http://jqueryvalidation.org/Validator.showErrors/
showErrors: function( errors ) {
if ( errors ) {
// add items to error list and map
$.extend( this.errorMap, errors );
this.errorList = [];
for ( var name in errors ) {
this.errorList.push({
message: errors[ name ],
element: this.findByName( name )[ 0 ]
});
}
// remove items from success list
this.successList = $.grep( this.successList, function( element ) {
return !( element.name in errors );
});
}
if ( this.settings.showErrors ) {
this.settings.showErrors.call( this, this.errorMap, this.errorList );
} else {
this.defaultShowErrors();
}
},
// http://jqueryvalidation.org/Validator.resetForm/
resetForm: function() {
if ( $.fn.resetForm ) {
$( this.currentForm ).resetForm();
}
this.submitted = {};
this.lastElement = null;
this.prepareForm();
this.hideErrors();
var i, elements = this.elements()
.removeData( "previousValue" )
.removeAttr( "aria-invalid" );
if ( this.settings.unhighlight ) {
for ( i = 0; elements[ i ]; i++ ) {
this.settings.unhighlight.call( this, elements[ i ],
this.settings.errorClass, "" );
}
} else {
elements.removeClass( this.settings.errorClass );
}
},
numberOfInvalids: function() {
return this.objectLength( this.invalid );
},
objectLength: function( obj ) {
/* jshint unused: false */
var count = 0,
i;
for ( i in obj ) {
count++;
}
return count;
},
hideErrors: function() {
this.hideThese( this.toHide );
},
hideThese: function( errors ) {
errors.not( this.containers ).text( "" );
this.addWrapper( errors ).hide();
},
valid: function() {
return this.size() === 0;
},
size: function() {
return this.errorList.length;
},
focusInvalid: function() {
if ( this.settings.focusInvalid ) {
try {
$( this.findLastActive() || this.errorList.length && this.errorList[ 0 ].element || [])
.filter( ":visible" )
.focus()
// manually trigger focusin event; without it, focusin handler isn't called, findLastActive won't have anything to find
.trigger( "focusin" );
} catch ( e ) {
// ignore IE throwing errors when focusing hidden elements
}
}
},
findLastActive: function() {
var lastActive = this.lastActive;
return lastActive && $.grep( this.errorList, function( n ) {
return n.element.name === lastActive.name;
}).length === 1 && lastActive;
},
elements: function() {
var validator = this,
rulesCache = {};
// select all valid inputs inside the form (no submit or reset buttons)
return $( this.currentForm )
.find( "input, select, textarea" )
.not( ":submit, :reset, :image, :disabled" )
.not( this.settings.ignore )
.filter( function() {
if ( !this.name && validator.settings.debug && window.console ) {
console.error( "%o has no name assigned", this );
}
// select only the first element for each name, and only those with rules specified
if ( this.name in rulesCache || !validator.objectLength( $( this ).rules() ) ) {
return false;
}
rulesCache[ this.name ] = true;
return true;
});
},
clean: function( selector ) {
return $( selector )[ 0 ];
},
errors: function() {
var errorClass = this.settings.errorClass.split( " " ).join( "." );
return $( this.settings.errorElement + "." + errorClass, this.errorContext );
},
reset: function() {
this.successList = [];
this.errorList = [];
this.errorMap = {};
this.toShow = $( [] );
this.toHide = $( [] );
this.currentElements = $( [] );
},
prepareForm: function() {
this.reset();
this.toHide = this.errors().add( this.containers );
},
prepareElement: function( element ) {
this.reset();
this.toHide = this.errorsFor( element );
},
elementValue: function( element ) {
var val,
$element = $( element ),
type = element.type;
if ( type === "radio" || type === "checkbox" ) {
return this.findByName( element.name ).filter(":checked").val();
} else if ( type === "number" && typeof element.validity !== "undefined" ) {
return element.validity.badInput ? false : $element.val();
}
val = $element.val();
if ( typeof val === "string" ) {
return val.replace(/\r/g, "" );
}
return val;
},
check: function( element ) {
element = this.validationTargetFor( this.clean( element ) );
var rules = $( element ).rules(),
rulesCount = $.map( rules, function( n, i ) {
return i;
}).length,
dependencyMismatch = false,
val = this.elementValue( element ),
result, method, rule;
for ( method in rules ) {
rule = { method: method, parameters: rules[ method ] };
try {
result = $.validator.methods[ method ].call( this, val, element, rule.parameters );
// if a method indicates that the field is optional and therefore valid,
// don't mark it as valid when there are no other rules
if ( result === "dependency-mismatch" && rulesCount === 1 ) {
dependencyMismatch = true;
continue;
}
dependencyMismatch = false;
if ( result === "pending" ) {
this.toHide = this.toHide.not( this.errorsFor( element ) );
return;
}
if ( !result ) {
this.formatAndAdd( element, rule );
return false;
}
} catch ( e ) {
if ( this.settings.debug && window.console ) {
console.log( "Exception occurred when checking element " + element.id + ", check the '" + rule.method + "' method.", e );
}
if ( e instanceof TypeError ) {
e.message += ". Exception occurred when checking element " + element.id + ", check the '" + rule.method + "' method.";
}
throw e;
}
}
if ( dependencyMismatch ) {
return;
}
if ( this.objectLength( rules ) ) {
this.successList.push( element );
}
return true;
},
// return the custom message for the given element and validation method
// specified in the element's HTML5 data attribute
// return the generic message if present and no method specific message is present
customDataMessage: function( element, method ) {
return $( element ).data( "msg" + method.charAt( 0 ).toUpperCase() +
method.substring( 1 ).toLowerCase() ) || $( element ).data( "msg" );
},
// return the custom message for the given element name and validation method
customMessage: function( name, method ) {
var m = this.settings.messages[ name ];
return m && ( m.constructor === String ? m : m[ method ]);
},
// return the first defined argument, allowing empty strings
findDefined: function() {
for ( var i = 0; i < arguments.length; i++) {
if ( arguments[ i ] !== undefined ) {
return arguments[ i ];
}
}
return undefined;
},
defaultMessage: function( element, method ) {
return this.findDefined(
this.customMessage( element.name, method ),
this.customDataMessage( element, method ),
// title is never undefined, so handle empty string as undefined
!this.settings.ignoreTitle && element.title || undefined,
$.validator.messages[ method ],
"<strong>Warning: No message defined for " + element.name + "</strong>"
);
},
formatAndAdd: function( element, rule ) {
var message = this.defaultMessage( element, rule.method ),
theregex = /\$?\{(\d+)\}/g;
if ( typeof message === "function" ) {
message = message.call( this, rule.parameters, element );
} else if ( theregex.test( message ) ) {
message = $.validator.format( message.replace( theregex, "{$1}" ), rule.parameters );
}
this.errorList.push({
message: message,
element: element,
method: rule.method
});
this.errorMap[ element.name ] = message;
this.submitted[ element.name ] = message;
},
addWrapper: function( toToggle ) {
if ( this.settings.wrapper ) {
toToggle = toToggle.add( toToggle.parent( this.settings.wrapper ) );
}
return toToggle;
},
defaultShowErrors: function() {
var i, elements, error;
for ( i = 0; this.errorList[ i ]; i++ ) {
error = this.errorList[ i ];
if ( this.settings.highlight ) {
this.settings.highlight.call( this, error.element, this.settings.errorClass, this.settings.validClass );
}
this.showLabel( error.element, error.message );
}
if ( this.errorList.length ) {
this.toShow = this.toShow.add( this.containers );
}
if ( this.settings.success ) {
for ( i = 0; this.successList[ i ]; i++ ) {
this.showLabel( this.successList[ i ] );
}
}
if ( this.settings.unhighlight ) {
for ( i = 0, elements = this.validElements(); elements[ i ]; i++ ) {
this.settings.unhighlight.call( this, elements[ i ], this.settings.errorClass, this.settings.validClass );
}
}
this.toHide = this.toHide.not( this.toShow );
this.hideErrors();
this.addWrapper( this.toShow ).show();
},
validElements: function() {
return this.currentElements.not( this.invalidElements() );
},
invalidElements: function() {
return $( this.errorList ).map(function() {
return this.element;
});
},
showLabel: function( element, message ) {
var place, group, errorID,
error = this.errorsFor( element ),
elementID = this.idOrName( element ),
describedBy = $( element ).attr( "aria-describedby" );
if ( error.length ) {
// refresh error/success class
error.removeClass( this.settings.validClass ).addClass( this.settings.errorClass );
// replace message on existing label
error.html( message );
} else {
// create error element
error = $( "<" + this.settings.errorElement + ">" )
.attr( "id", elementID + "-error" )
.addClass( this.settings.errorClass )
.html( message || "" );
// Maintain reference to the element to be placed into the DOM
place = error;
if ( this.settings.wrapper ) {
// make sure the element is visible, even in IE
// actually showing the wrapped element is handled elsewhere
place = error.hide().show().wrap( "<" + this.settings.wrapper + "/>" ).parent();
}
if ( this.labelContainer.length ) {
this.labelContainer.append( place );
} else if ( this.settings.errorPlacement ) {
this.settings.errorPlacement( place, $( element ) );
} else {
place.insertAfter( element );
}
// Link error back to the element
if ( error.is( "label" ) ) {
// If the error is a label, then associate using 'for'
error.attr( "for", elementID );
} else if ( error.parents( "label[for='" + elementID + "']" ).length === 0 ) {
// If the element is not a child of an associated label, then it's necessary
// to explicitly apply aria-describedby
errorID = error.attr( "id" ).replace( /(:|\.|\[|\]|\$)/g, "\\$1");
// Respect existing non-error aria-describedby
if ( !describedBy ) {
describedBy = errorID;
} else if ( !describedBy.match( new RegExp( "\\b" + errorID + "\\b" ) ) ) {
// Add to end of list if not already present
describedBy += " " + errorID;
}
$( element ).attr( "aria-describedby", describedBy );
// If this element is grouped, then assign to all elements in the same group
group = this.groups[ element.name ];
if ( group ) {
$.each( this.groups, function( name, testgroup ) {
if ( testgroup === group ) {
$( "[name='" + name + "']", this.currentForm )
.attr( "aria-describedby", error.attr( "id" ) );
}
});
}
}
}
if ( !message && this.settings.success ) {
error.text( "" );
if ( typeof this.settings.success === "string" ) {
error.addClass( this.settings.success );
} else {
this.settings.success( error, element );
}
}
this.toShow = this.toShow.add( error );
},
errorsFor: function( element ) {
var name = this.idOrName( element ),
describer = $( element ).attr( "aria-describedby" ),
selector = "label[for='" + name + "'], label[for='" + name + "'] *";
// aria-describedby should directly reference the error element
if ( describer ) {
selector = selector + ", #" + describer.replace( /\s+/g, ", #" );
}
return this
.errors()
.filter( selector );
},
idOrName: function( element ) {
return this.groups[ element.name ] || ( this.checkable( element ) ? element.name : element.id || element.name );
},
validationTargetFor: function( element ) {
// If radio/checkbox, validate first element in group instead
if ( this.checkable( element ) ) {
element = this.findByName( element.name );
}
// Always apply ignore filter
return $( element ).not( this.settings.ignore )[ 0 ];
},
checkable: function( element ) {
return ( /radio|checkbox/i ).test( element.type );
},
findByName: function( name ) {
return $( this.currentForm ).find( "[name='" + name + "']" );
},
getLength: function( value, element ) {
switch ( element.nodeName.toLowerCase() ) {
case "select":
return $( "option:selected", element ).length;
case "input":
if ( this.checkable( element ) ) {
return this.findByName( element.name ).filter( ":checked" ).length;
}
}
return value.length;
},
depend: function( param, element ) {
return this.dependTypes[typeof param] ? this.dependTypes[typeof param]( param, element ) : true;
},
dependTypes: {
"boolean": function( param ) {
return param;
},
"string": function( param, element ) {
return !!$( param, element.form ).length;
},
"function": function( param, element ) {
return param( element );
}
},
optional: function( element ) {
var val = this.elementValue( element );
return !$.validator.methods.required.call( this, val, element ) && "dependency-mismatch";
},
startRequest: function( element ) {
if ( !this.pending[ element.name ] ) {
this.pendingRequest++;
this.pending[ element.name ] = true;
}
},
stopRequest: function( element, valid ) {
this.pendingRequest--;
// sometimes synchronization fails, make sure pendingRequest is never < 0
if ( this.pendingRequest < 0 ) {
this.pendingRequest = 0;
}
delete this.pending[ element.name ];
if ( valid && this.pendingRequest === 0 && this.formSubmitted && this.form() ) {
$( this.currentForm ).submit();
this.formSubmitted = false;
} else if (!valid && this.pendingRequest === 0 && this.formSubmitted ) {
$( this.currentForm ).triggerHandler( "invalid-form", [ this ]);
this.formSubmitted = false;
}
},
previousValue: function( element ) {
return $.data( element, "previousValue" ) || $.data( element, "previousValue", {
old: null,
valid: true,
message: this.defaultMessage( element, "remote" )
});
},
// cleans up all forms and elements, removes validator-specific events
destroy: function() {
this.resetForm();
$( this.currentForm )
.off( ".validate" )
.removeData( "validator" );
}
},
classRuleSettings: {
required: { required: true },
email: { email: true },
url: { url: true },
date: { date: true },
dateISO: { dateISO: true },
number: { number: true },
digits: { digits: true },
cardno: { cardno: true },
carnum: { carnum: true },
creditcard: { creditcard: true },
xiaoshu:{xiaoshu:true},
telnet:{telnet:true},
ip:{ip:true},
enNumUnderline:{enNumUnderline:true},
nocn:{nocn:true}
},
addClassRules: function( className, rules ) {
if ( className.constructor === String ) {
this.classRuleSettings[ className ] = rules;
} else {
$.extend( this.classRuleSettings, className );
}
},
classRules: function( element ) {
var rules = {},
classes = $( element ).attr( "class" );
if ( classes ) {
$.each( classes.split( " " ), function() {
if ( this in $.validator.classRuleSettings ) {
$.extend( rules, $.validator.classRuleSettings[ this ]);
}
});
}
return rules;
},
normalizeAttributeRule: function( rules, type, method, value ) {
// convert the value to a number for number inputs, and for text for backwards compability
// allows type="date" and others to be compared as strings
if ( /min|max/.test( method ) && ( type === null || /number|range|text/.test( type ) ) ) {
value = Number( value );
// Support Opera Mini, which returns NaN for undefined minlength
if ( isNaN( value ) ) {
value = undefined;
}
}
if ( value || value === 0 ) {
rules[ method ] = value;
} else if ( type === method && type !== "range" ) {
// exception: the jquery validate 'range' method
// does not test for the html5 'range' type
rules[ method ] = true;
}
},
attributeRules: function( element ) {
var rules = {},
$element = $( element ),
type = element.getAttribute( "type" ),
method, value;
for ( method in $.validator.methods ) {
// support for <input required> in both html5 and older browsers
if ( method === "required" ) {
value = element.getAttribute( method );
// Some browsers return an empty string for the required attribute
// and non-HTML5 browsers might have required="" markup
if ( value === "" ) {
value = true;
}
// force non-HTML5 browsers to return bool
value = !!value;
} else {
value = $element.attr( method );
}
this.normalizeAttributeRule( rules, type, method, value );
}
// maxlength may be returned as -1, 2147483647 ( IE ) and 524288 ( safari ) for text inputs
if ( rules.maxlength && /-1|2147483647|524288/.test( rules.maxlength ) ) {
delete rules.maxlength;
}
return rules;
},
dataRules: function( element ) {
var rules = {},
$element = $( element ),
type = element.getAttribute( "type" ),
method, value;
for ( method in $.validator.methods ) {
value = $element.data( "rule" + method.charAt( 0 ).toUpperCase() + method.substring( 1 ).toLowerCase() );
this.normalizeAttributeRule( rules, type, method, value );
}
return rules;
},
staticRules: function( element ) {
var rules = {},
validator = $.data( element.form, "validator" );
if ( validator.settings.rules ) {
rules = $.validator.normalizeRule( validator.settings.rules[ element.name ] ) || {};
}
return rules;
},
normalizeRules: function( rules, element ) {
// handle dependency check
$.each( rules, function( prop, val ) {
// ignore rule when param is explicitly false, eg. required:false
if ( val === false ) {
delete rules[ prop ];
return;
}
if ( val.param || val.depends ) {
var keepRule = true;
switch ( typeof val.depends ) {
case "string":
keepRule = !!$( val.depends, element.form ).length;
break;
case "function":
keepRule = val.depends.call( element, element );
break;
}
if ( keepRule ) {
rules[ prop ] = val.param !== undefined ? val.param : true;
} else {
delete rules[ prop ];
}
}
});
// evaluate parameters
$.each( rules, function( rule, parameter ) {
rules[ rule ] = $.isFunction( parameter ) ? parameter( element ) : parameter;
});
// clean number parameters
$.each([ "minlength", "maxlength" ], function() {
if ( rules[ this ] ) {
rules[ this ] = Number( rules[ this ] );
}
});
$.each([ "rangelength", "range" ], function() {
var parts;
if ( rules[ this ] ) {
if ( $.isArray( rules[ this ] ) ) {
rules[ this ] = [ Number( rules[ this ][ 0 ]), Number( rules[ this ][ 1 ] ) ];
} else if ( typeof rules[ this ] === "string" ) {
parts = rules[ this ].replace(/[\[\]]/g, "" ).split( /[\s,]+/ );
rules[ this ] = [ Number( parts[ 0 ]), Number( parts[ 1 ] ) ];
}
}
});
if ( $.validator.autoCreateRanges ) {
// auto-create ranges
if ( rules.min != null && rules.max != null ) {
rules.range = [ rules.min, rules.max ];
delete rules.min;
delete rules.max;
}
if ( rules.minlength != null && rules.maxlength != null ) {
rules.rangelength = [ rules.minlength, rules.maxlength ];
delete rules.minlength;
delete rules.maxlength;
}
}
return rules;
},
// Converts a simple string to a {string: true} rule, e.g., "required" to {required:true}
normalizeRule: function( data ) {
if ( typeof data === "string" ) {
var transformed = {};
$.each( data.split( /\s/ ), function() {
transformed[ this ] = true;
});
data = transformed;
}
return data;
},
// http://jqueryvalidation.org/jQuery.validator.addMethod/
addMethod: function( name, method, message ) {
$.validator.methods[ name ] = method;
$.validator.messages[ name ] = message !== undefined ? message : $.validator.messages[ name ];
if ( method.length < 3 ) {
$.validator.addClassRules( name, $.validator.normalizeRule( name ) );
}
},
methods: {
// http://jqueryvalidation.org/required-method/
required: function( value, element, param ) {
// check if dependency is met
if ( !this.depend( param, element ) ) {
return "dependency-mismatch";
}
if ( element.nodeName.toLowerCase() === "select" ) {
// could be an array for select-multiple or a string, both are fine this way
var val = $( element ).val();
return val && val.length > 0;
}
if ( this.checkable( element ) ) {
return this.getLength( value, element ) > 0;
}
return value.length > 0;
},
// http://jqueryvalidation.org/email-method/
email: function( value, element ) {
// From https://html.spec.whatwg.org/multipage/forms.html#valid-e-mail-address
// Retrieved 2014-01-14
// If you have a problem with this implementation, report a bug against the above spec
// Or use custom methods to implement your own email validation
return this.optional( element ) || /^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/.test( value );
},
// http://jqueryvalidation.org/url-method/
url: function( value, element ) {
// Copyright (c) 2010-2013 Diego Perini, MIT licensed
// https://gist.github.com/dperini/729294
// see also https://mathiasbynens.be/demo/url-regex
// modified to allow protocol-relative URLs
return this.optional( element ) || /^(?:(?:(?:https?|ftp):)?\/\/)(?:\S+(?::\S*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})).?)(?::\d{2,5})?(?:[/?#]\S*)?$/i.test( value );
},
//身份证号码
cardno: function( value, element ) {
return this.optional( element ) || /^[1-9]\d{7}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}$|^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}([0-9]|X)$/.test( value );
},
//车牌号码
carnum: function( value, element ) {
return this.optional( element ) || /^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领A-Z]{1}[A-Z]{1}[警京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼]{0,1}[A-Z0-9]{4}[A-Z0-9挂学警港澳]{1}$/.test( value );
},
xiaoshu: function(value, element) {
var tel = /^(([0-9]+[\.]?[0-9]{1,2})|[1-9])$/;
return this.optional(element) || (tel.test(value));
},
telnet: function(value, element) {
var reg =/^(\(\d{3,4}\)|\d{3,4}-|\s)?\d{7,14}$/;
var tel =/^1[34578]\d{9}$/;
/* var reg = /^[^-].*[^-]$/;//验证开头不为-
var tel = /^[0-9-]*$/;//验证内容是数字和-
*/// /^[\d\-]\d*\-*$/
// ^[1-9-]+[0-9-]*$ //只能刷数字和-前面不能为0(^[0-9-]*$)+
return this.optional(element) || ((reg.test(value)) || (tel.test(value)));
},
//IP验证
ip: function(value, element) {
// var ip = /^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$/;
// return this.optional(element) || (ip.test(value));
var ip = /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/;
return this.optional(element) || (ip.test(value) && (RegExp.$1 < 256 && RegExp.$2 < 256 && RegExp.$3 < 256 && RegExp.$4 < 256));
},
nocn: function(value, element) {
var val = /^[0-9a-zA-Z-]*$/;//验证内容是数字,字母和-
return this.optional(element) || (val.test(value));
},
enNumUnderline: function(value, element) {
var val = /^[0-9a-zA-Z_]*$/;//验证内容是数字,字母和-
return this.optional(element) || (val.test(value));
},
// http://jqueryvalidation.org/date-method/
date: function( value, element ) {
return this.optional( element ) || !/Invalid|NaN/.test( new Date( value ).toString() );
},
// http://jqueryvalidation.org/dateISO-method/
dateISO: function( value, element ) {
return this.optional( element ) || /^\d{4}[\/\-](0?[1-9]|1[012])[\/\-](0?[1-9]|[12][0-9]|3[01])$/.test( value );
},
// http://jqueryvalidation.org/number-method/
number: function( value, element ) {
return this.optional( element ) || /^(?:-?\d+|-?\d{1,3}(?:,\d{3})+)?(?:\.\d+)?$/.test( value );
},
// http://jqueryvalidation.org/digits-method/
digits: function( value, element ) {
return this.optional( element ) || /^\d+$/.test( value );
},
// http://jqueryvalidation.org/creditcard-method/
// based on http://en.wikipedia.org/wiki/Luhn_algorithm
creditcard: function( value, element ) {
if ( this.optional( element ) ) {
return "dependency-mismatch";
}
// accept only spaces, digits and dashes
if ( /[^0-9 \-]+/.test( value ) ) {
return false;
}
var nCheck = 0,
nDigit = 0,
bEven = false,
n, cDigit;
value = value.replace( /\D/g, "" );
// Basing min and max length on
// http://developer.ean.com/general_info/Valid_Credit_Card_Types
if ( value.length < 13 || value.length > 19 ) {
return false;
}
for ( n = value.length - 1; n >= 0; n--) {
cDigit = value.charAt( n );
nDigit = parseInt( cDigit, 10 );
if ( bEven ) {
if ( ( nDigit *= 2 ) > 9 ) {
nDigit -= 9;
}
}
nCheck += nDigit;
bEven = !bEven;
}
return ( nCheck % 10 ) === 0;
},
// http://jqueryvalidation.org/minlength-method/
minlength: function( value, element, param ) {
var length = $.isArray( value ) ? value.length : this.getLength( value, element );
return this.optional( element ) || length >= param;
},
// http://jqueryvalidation.org/maxlength-method/
maxlength: function( value, element, param ) {
var length = $.isArray( value ) ? value.length : this.getLength( value, element );
return this.optional( element ) || length <= param;
},
// http://jqueryvalidation.org/rangelength-method/
rangelength: function( value, element, param ) {
var length = $.isArray( value ) ? value.length : this.getLength( value, element );
return this.optional( element ) || ( length >= param[ 0 ] && length <= param[ 1 ] );
},
// http://jqueryvalidation.org/min-method/
min: function( value, element, param ) {
return this.optional( element ) || value >= param;
},
// http://jqueryvalidation.org/max-method/
max: function( value, element, param ) {
return this.optional( element ) || value <= param;
},
// http://jqueryvalidation.org/range-method/
range: function( value, element, param ) {
return this.optional( element ) || ( value >= param[ 0 ] && value <= param[ 1 ] );
},
// http://jqueryvalidation.org/equalTo-method/
equalTo: function( value, element, param ) {
// bind to the blur event of the target in order to revalidate whenever the target field is updated
// TODO find a way to bind the event just once, avoiding the unbind-rebind overhead
//var target = $( param );
var target = $(element.form).find( param );/**-修正bug在不同的页面调用valid方法时找不到元素的bug-*/
if ( this.settings.onfocusout ) {
target.off( ".validate-equalTo" ).on( "blur.validate-equalTo", function() {
$( element ).valid();
});
}
return value === target.val();
},
// http://jqueryvalidation.org/remote-method/
remote: function( value, element, param ) {
if ( this.optional( element ) ) {
return "dependency-mismatch";
}
var previous = this.previousValue( element ),
validator, data;
if (!this.settings.messages[ element.name ] ) {
this.settings.messages[ element.name ] = {};
}
previous.originalMessage = this.settings.messages[ element.name ].remote;
this.settings.messages[ element.name ].remote = previous.message;
param = typeof param === "string" && { url: param } || param;
if ( previous.old === value ) {
return previous.valid;
}
previous.old = value;
validator = this;
this.startRequest( element );
data = {};
data[ element.name ] = value;
$.ajax( $.extend( true, {
mode: "abort",
port: "validate" + element.name,
dataType: "json",
data: data,
context: validator.currentForm,
success: function( response ) {
var valid = response === true || response === "true",
errors, message, submitted;
validator.settings.messages[ element.name ].remote = previous.originalMessage;
if ( valid ) {
submitted = validator.formSubmitted;
validator.prepareElement( element );
validator.formSubmitted = submitted;
validator.successList.push( element );
delete validator.invalid[ element.name ];
validator.showErrors();
} else {
errors = {};
message = response || validator.defaultMessage( element, "remote" );
errors[ element.name ] = previous.message = $.isFunction( message ) ? message( value ) : message;
validator.invalid[ element.name ] = true;
validator.showErrors( errors );
}
previous.valid = valid;
validator.stopRequest( element, valid );
}
}, param ) );
return "pending";
}
}
});
// ajax mode: abort
// usage: $.ajax({ mode: "abort"[, port: "uniqueport"]});
// if mode:"abort" is used, the previous request on that port (port can be undefined) is aborted via XMLHttpRequest.abort()
var pendingRequests = {},
ajax;
// Use a prefilter if available (1.5+)
if ( $.ajaxPrefilter ) {
$.ajaxPrefilter(function( settings, _, xhr ) {
var port = settings.port;
if ( settings.mode === "abort" ) {
if ( pendingRequests[port] ) {
pendingRequests[port].abort();
}
pendingRequests[port] = xhr;
}
});
} else {
// Proxy ajax
ajax = $.ajax;
$.ajax = function( settings ) {
var mode = ( "mode" in settings ? settings : $.ajaxSettings ).mode,
port = ( "port" in settings ? settings : $.ajaxSettings ).port;
if ( mode === "abort" ) {
if ( pendingRequests[port] ) {
pendingRequests[port].abort();
}
pendingRequests[port] = ajax.apply(this, arguments);
return pendingRequests[port];
}
return ajax.apply(this, arguments);
};
}
}));