前言:上一篇详细的介绍了jQuery.validator( 版本v1.13.0 )的验证规则,这一篇重点讲述它的源码结构,及如何来对元素进行验证,错误消息提示的内部实现

一、插件结构(组织方式)

在讲述如何对元素进行验证前有必要了解它的代码组织方式,请看代码(部分省略)

var plugFn = function( $ ) {
$.extend($.fn, {
// 验证from表单
validate: function( options ) {
// ...
// 实例化$.validator对象
var validator = new $.validator( options, this[0] );
// 当表单提交时,通过调用$.validator的原型方法form来验证表单元素
this.onsubmit(function(){
if ( validator.form() ){
return true;
}
return false;
});
},
// 获取元素的验证规则,需要逐一验证
rules: function( command, argument ) {
// ...
}
}); // constructor for validator
// 构造函数
$.validator = function( options, form ) {
this.settings = $.extend( true, {}, $.validator.defaults, options );
this.currentForm = form;
this.init();
}; $.extend( $.validator, {
// 定义$.validator的属性,方法
defaults: { },
setDefaults: function( settings ) { },
// ...
// 供$.validator实例使用
prototype: {
init: function() {
// ...
// 初始化代码
},
form: function() { },
checkForm: function() { },
elements: function() { },
check: function( element ) { },
showErrors: function( errors ) { },
valid: function() {
return this.size() === 0;
},
size: function() {
return this.errorList.length;
},
// ...
}
});
// ...
};

首先将实现插件的代码包装为一个函数,因为插件是需要在jQuery上定义的,因此调用plugFn函数需要传递参数 jQuery 或 $ 变量;在插件中定义了构造函数 $.validator 及其属性,方法,以及 原型对象方法,在扩展$.fn的原型方法validate中,实例化了一个
$.validator对象,并调用实例方法,这就是插件的整个实现逻辑。

// 为了兼容 requirejs(requirejs遵循AMD规范),将代码包装为如下:

(function( factory ) {
if ( typeof define === "function" && define.amd ) {
define( ["jquery"], factory );
} else {
factory( jQuery );
}
}( plugFn ));

当define类型为函数,且存在define.amd,代码执行如下:

// 需配置好 jquery 引用路径
require.config({
paths: {
jquery: 'jquery-1.11.1'
}
}); // 其中的匿名函数就是 上面的 plugFn 函数
define(['jquery'], function( $ ){
// 插件实现
});

二、如何对表单元素验证

验证的触发方式:

1、表单提交:将会对所有不是可选的表单元素进行验证

2、当触发focusout事件,且表单元素value不为空(即是必需的,不是可选的),则会对事件目标元素进行验证

3、当触发focusin事件,且在focusout事件中对目标元素验证过,才会在focusin事件中对目标元素进行验证

如何验证:

首先获取元素的匹配规则,然后轮循匹配规则,进行验证

$(ele).rules();
validator.check(ele);

如果验证未通过,将会把元素的name,rule,message记录给 validator.errorList 数组,并且会生成一个包含错误消息的label元素,插入在表单元素的后面
检测所有表单元素是否通过验证只需判断 validator.errorList === 0;

三、配置对象

{
errorClass: "error", // 消息错误提示容器,验证未通过的表单元素的的className
validClass: "valid", // 验证通过的表单元素的的className
errorElement: "label", // 消息错误提示容器的的tagName
wrapper: element.tagName, // 只能是一个标签名,如:div, strong ...,将会创建一个div元素包裹 错误消息提示的label元素
errorLabelContainer: selector, // 如果表单验证不通过,所有错误消息提示的label元素都会插入到该元素中 debug: true, // 为true将会 阻止表单提交,但会验证表单控件
ignore: ':hidden', // 将会忽略选择器匹配的所有表单元素的验证
submitHandler: function(){ // 表单提交时,将会触发这个函数,如果存在该函数,将会阻止表单提交 },
invalidHandler: function(){ // 如果表单验证不通过,将会触发这个函数 }
}

为表单元素添加验证规则的配置请见:jQuery.validator 验证规则详解

小提示:设置debug为true,将会阻止表单提交,但会验证表单;还有一种相反的行为,不会验证表单,直接提交,那就需要在提交按钮的 class 属性上加一个 cancel 的className 或者 加上一个HTML5的 formnovalidate 属性;

四、自定义你的错误消息提示文案

$.validator.messages = {
required: "输入不能为空.",
remote: "用户名已经存在.", // 自己定义
email: "请输入一个有效的电子邮件地址.",
url: "请输入一个有效的URL.",
date: "请输入一个有效的日期.",
dateISO: "请输入一个有效的日期 ( ISO ) ( 例:2014/08/28 ).",
number: "请输入一个有效的数字.",
digits: "请输入一个正整数.",
creditcard: "请输入一个有效的信用卡号.",
equalTo: "请再次输入相同的值.",
maxlength: $.validator.format( "请输入不超过{0}个字符." ),
minlength: $.validator.format( "请输入至少{0}个字符." ),
rangelength: $.validator.format( "请输入一个字符长{0}至{1}的字符." ),
range: $.validator.format( "请输入一个{0}至{1}的数." ),
max: $.validator.format( "请输入一个值小于或等于{0}的数." ),
min: $.validator.format( "请输入一个值大于或等于{0}的数." )
};

看看上面的代码,怎么出现了类似这种 $.validator.format( "请输入不超过{0}个字符." ) 值呢

直接看源码:

$.validator.format = function( source, params ) {
// 只传递了一个参数
if ( arguments.length === 1 ) {
// 返回一个匿名函数,调用的时候肯定会带上参数的,别急
return function() {
var args = $.makeArray( arguments );
// 将source插入到最前面
args.unshift( source ); // 如果匿名函数带上了参数,将会执行$.validator.format后面的部分代码了,否则永远都是执行前面的代码
return $.validator.format.apply( this, args );
};
} // 参数个数大于2, 如:$.validator.format(source, 10, 20)
if ( arguments.length > 2 && params.constructor !== Array ) {
params = $.makeArray( arguments ).slice( 1 );
}
// 参数个数等于2, 如:$.validator.format(source, 10)
if ( params.constructor !== Array ) {
params = [ params ];
} // 将 {0} 或 {1} 替换成真正的实参
$.each( params, function( i, n ) {
source = source.replace( new RegExp( "\\{" + i + "\\}", "g" ), function() {
return n;
});
});
return source;
};

看看怎么来使用它:

// $.validator.format使用实例

$.validator.messages.maxlength(4); // "请输入不超过4个字符."
$.validator.messages.range(10, 100); // "请输入一个10至100的数."

五、源码

最后附上源码,未解析,供给愿意看的同学看

/*!
* jQuery Validation Plugin v1.13.0
*
* http://jqueryvalidation.org/
*
* Copyright (c) 2014 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.validateDelegate( ":submit", "click", function( event ) {
if ( validator.settings.submitHandler ) {
validator.submitButton = event.target;
}
// allow suppressing validation by adding a cancel class to the submit button
if ( $( event.target ).hasClass( "cancel" ) ) {
validator.cancelSubmit = true;
} // allow suppressing validation by adding the html5 formnovalidate attribute to the submit button
if ( $( event.target ).attr( "formnovalidate" ) !== undefined ) {
validator.cancelSubmit = true;
}
}); // validate the form on submit
this.submit( function( event ) {
if ( validator.settings.debug ) {
// prevent form submit to be able to see console output
event.preventDefault();
}
function handle() {
var hidden;
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 );
}
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();
}
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; if ( $( this[ 0 ] ).is( "form" ) ) {
valid = this.validate().form();
} else {
valid = true;
validator = $( this[ 0 ].form ).validate();
this.each( function() {
valid = validator.element( this ) && valid;
});
}
return valid;
},
// attributes: space separated list of attributes to retrieve and remove
removeAttrs: function( attributes ) {
var result = {},
$element = this;
$.each( attributes.split( /\s/ ), function( index, value ) {
result[ value ] = $element.attr( value );
$element.removeAttr( value );
});
return result;
},
// 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",
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 && !this.blockFocusCleanup ) {
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 ) {
if ( event.which === 9 && this.elementValue( element ) === "" ) {
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[ 0 ].form, "validator" ),
eventType = "on" + event.type.replace( /^validate/, "" ),
settings = validator.settings;
if ( settings[ eventType ] && !this.is( settings.ignore ) ) {
settings[ eventType ].call( validator, this[ 0 ], event );
}
}
$( this.currentForm )
.validateDelegate( ":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']",
"focusin focusout keyup", delegate)
// Support: Chrome, oldIE
// "select" is provided as event.target when clicking a option
.validateDelegate("select, option, [type='radio'], [type='checkbox']", "click", delegate); if ( this.settings.invalidHandler ) {
$( this.currentForm ).bind( "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();
this.elements()
.removeClass( this.settings.errorClass )
.removeData( "previousValue" )
.removeAttr( "aria-invalid" );
}, 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 $( "input[name='" + element.name + "']: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 );
}
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" );
// 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 ).not( this.settings.ignore )[ 0 ];
}
return element;
}, 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" )
});
} }, classRuleSettings: {
required: { required: true },
email: { email: true },
url: { url: true },
date: { date: true },
dateISO: { dateISO: true },
number: { number: true },
digits: { digits: true },
creditcard: { creditcard: 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;
}, 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 );
} // 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 );
} 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;
}
} // 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 method, value,
rules = {}, $element = $( element );
for ( method in $.validator.methods ) {
value = $element.data( "rule" + method.charAt( 0 ).toUpperCase() + method.substring( 1 ).toLowerCase() );
if ( value !== undefined ) {
rules[ 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 && rules.max ) {
rules.range = [ rules.min, rules.max ];
delete rules.min;
delete rules.max;
}
if ( rules.minlength && rules.maxlength ) {
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 $.trim( value ).length > 0;
}, // http://jqueryvalidation.org/email-method/
email: function( value, element ) {
// From http://www.whatwg.org/specs/web-apps/current-work/multipage/states-of-the-type-attribute.html#e-mail-state-%28type=email%29
// 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 ) {
// contributed by Scott Gonzalez: http://projects.scottsplayground.com/iri/
return this.optional( element ) || /^(https?|s?ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i.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/
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( $.trim( 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( $.trim( 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( $.trim( 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 );
if ( this.settings.onfocusout ) {
target.unbind( ".validate-equalTo" ).bind( "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, {
url: param,
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";
} } }); $.format = function deprecated() {
throw "$.format has been deprecated. Please use $.validator.format instead.";
}; // 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);
};
} // provides delegate(type: String, delegate: Selector, handler: Callback) plugin for easier event delegation
// handler is only called when $(event.target).is(delegate), in the scope of the jquery-object for event.target $.extend($.fn, {
validateDelegate: function( delegate, type, handler ) {
return this.bind(type, function( event ) {
var target = $(event.target);
if ( target.is(delegate) ) {
return handler.apply(target, arguments);
}
});
}
}); }));

注:对jQuery.validator详解到此为止,有不对的地方,欢迎大家拍砖指正,如果你觉得本文对你有用,请竖起你的大拇指,转载请注明出处:博客园 华子yjh,谢谢!

jQuery.validator 详解二的更多相关文章

  1. jQuery.validator 详解

    jQuery.validator 详解二 前言:上一篇详细的介绍了jQuery.validator( 版本v1.13.0 )的验证规则,这一篇重点讲述它的源码结构,及如何来对元素进行验证,错误消息提示 ...

  2. jquery.validate详解二

    五.常用方法及注意问题 1.用其他方式替代默认的SUBMIT $().ready(function() {  $("#signupForm").validate({         ...

  3. jquery validate 详解二

    原文:http://blog.sina.com.cn/s/blog_608475eb0100h3h2.html 这里只是第二篇,前面的内容请参阅上一篇 五.常用方法及注意问题 1.用其他方式替代默认的 ...

  4. jQuery:详解jQuery中的事件(二)

    上一篇讲到jQuery中的事件,深入学习了加载DOM和事件绑定的相关知识,这篇主要深入讨论jQuery事件中的合成事件.事件冒泡和事件移除等内容. 接上篇jQuery:详解jQuery中的事件(一) ...

  5. Jquery 选择器 详解 js 判断字符串是否包含另外一个字符串

    Jquery 选择器 详解   在线文档地址:http://tool.oschina.net/apidocs/apidoc?api=jquery 各种在线工具地址:http://www.ostools ...

  6. .NET DLL 保护措施详解(二)关于性能的测试

    先说结果: 加了缓存的结果与C#原生代码差异不大了 我对三种方式进行了测试: 第一种,每次调用均动态编译 第二种,缓存编译好的对象 第三种,直接调用原生C#代码 .net dll保护系列 ------ ...

  7. jquery方法详解

    jquery方法详解 http://www.365mini.com/doc

  8. PopUpWindow使用详解(二)——进阶及答疑

      相关文章:1.<PopUpWindow使用详解(一)——基本使用>2.<PopUpWindow使用详解(二)——进阶及答疑> 上篇为大家基本讲述了有关PopupWindow ...

  9. Android 布局学习之——Layout(布局)详解二(常见布局和布局参数)

    [Android布局学习系列]   1.Android 布局学习之——Layout(布局)详解一   2.Android 布局学习之——Layout(布局)详解二(常见布局和布局参数)   3.And ...

随机推荐

  1. javaScript与MVC

    MVC,就是Module,View,Controller分离,使业务逻辑更加清晰,但是现在公司的项目中很多地方那个不是这样的,很多业务逻辑放在了javascript中实现,这样做的优点就是对于技术要求 ...

  2. poj 2653 线段相交

    题意:一堆线段依次放在桌子上,上面的线段会压住下面的线段,求找出没被压住的线段. sol:从下向上找,如果发现上面的线段与下面的相交,说明被压住了.break掉 其实这是个n^2的算法,但是题目已经说 ...

  3. EF-CodeFirst 继承关系TPH、TPT、TPC

    继承关系 面向对象的三大特征之一:继承 ,在开发中起到了重要的作用.我们的实体本身也是类,继承自然是没有问题.下面开始分析 EF里的继承映射关系TPH.TPT.TPC 现在我们有这样一个需求,用户里要 ...

  4. [Android]加密技术

    对称加密无论是加密还是解密都使用同一个key,而非对称加密需要两个key(public key和private key).使用public key对数据进行加密,必须使用private key对数据进 ...

  5. 导入.pch文件

    Xcode5中创建一个工程的时候,系统会自动创建一个以以工程名为名字的pch(Precompile Prefix Header)文件,开发的过程中可以将广泛使用的头文件以及宏包含在该文件下,编译器就会 ...

  6. Beta版本——第五次冲刺博客

    我说的都队 031402304 陈燊 031402342 许玲玲 031402337 胡心颖 03140241 王婷婷 031402203 陈齐民 031402209 黄伟炜 031402233 郑扬 ...

  7. BZOJ1588[HNOI2002]营业额统计

    传送门 平衡树常规题,给出两种实现算法 Treap版: //OJ 1610 //by Cydiater //2016.9.1 #include <iostream> #include &l ...

  8. uC/OS-II互斥信号(OS_mutex)块

    /*************************************************************************************************** ...

  9. 初识Hadoop一,配置及启动服务

    一.Hadoop简介: Hadoop是由Apache基金会所开发的分布式系统基础架构,实现了一个分布式文件系统(Hadoop Distributed File System),简称HDFS:Hadoo ...

  10. centos7.2安装paramiko报error: command 'gcc' failed with exit status 1的解决办法

    安装依赖 yum install kernel-devel libxslt-devel libffi-devel python-devel mysql-devel zlib-devel openssl ...