虽然现在MVC比较热, 但是使用Web Form方式进行开发的项目应该还有很多,这就少不了使用验证控件,但是验证控件在验证不通过时,提醒的方式很简单,不够友好。如果页面布局是流布局方式,很容易因为显示出来的错误信息造成布局混乱。AjaxControlToolkit的ValidatorCallout虽然可以很好,但是需要为每一个验证控件要再加多一个控件, 在实际使用中太麻烦了,于是分析了ValidatorCallout的原理后,自己来实现一个更好用的ValidatorCallout
原理: 每一个验证控件最后都会在页面中生成相应的元素,并有一个
evaluationfunction属性,这个方法会在验证的时候被调用, AjaxControlToolkit中就是通过重写这个方法来达到提示的目的。
// // Override the evaluation method of the current validator // if (elt.evaluationfunction) { this ._originalValidationMethod = Function.createDelegate(elt, elt.evaluationfunction); this ._validationMethodOverride = Function.createDelegate( this , this ._onvalidate); elt.evaluationfunction = this ._validationMethodOverride; }
新的
ValidatorCallout实现方式与这个类似,由于所有的验证控件都在 Page_Validators这个数组中,这个是由验证控件自动生成的,所以应该不用再给每一个验证控件都再加一个控件,只引用相应的脚本就可以了,不用添加修改任何代码。
实现方式:
var ValidatorCallout = function (validator) {
if (typeof (validator) =='string')
this ._validator = document.getElementById(validator); else this ._validator = validator; this ._validator.display = ' None ' ; // the error message will not show when validate if ( typeof (validator.controltovalidate) == ' string ' ) { this ._validatorControl = document.getElementById(validator.controltovalidate); } else { this ._validatorControl = null ; } } ValidatorCallout.zIndex = 999 ; ValidatorCallout.prototype = { initiate: function () { var divContainer = $( ' <div id=" ' + ' Validator_divContainer ' + ValidatorCallout.zIndex + ' "></div> ' ) .addClass( ' tip_Container ' ).css( ' zIndex ' , ValidatorCallout.zIndex ++ ) .click( function () { $( this ).css( ' zIndex ' , ValidatorCallout.zIndex ++ ); }); this ._divContainer = divContainer[ 0 ]; var divCorner = $( ' <div></div> ' ).addClass( ' tip_Corner ' ).appendTo(divContainer); var count = 10 ; if ($.browser.msie == true && $.browser.version == ' 6.0 ' ) { count = 5 ; /* special for ie 6.0 */ } for ( var i = 0 ; i < count; i ++ ) { $( ' <div></div> ' ).css( ' width ' , i + ' px ' ) .addClass( ' tip_Corner_Line ' ).appendTo(divCorner); } var divPanel = $( ' <div></div> ' ).addClass( ' tip_Panel ' ).appendTo(divContainer); $( ' <span></span> ' ).addClass( ' tip-message ' ) .text( this ._validator.errormessage == null ? '' : this ._validator.errormessage) .appendTo(divPanel); $( ' <div></div> ' ).addClass( ' tip_close ' ).appendTo(divPanel) .click( function () { divContainer.css( ' display ' , ' none ' ); }); $( ' body ' ).append(divContainer); this ._validator.callout = this ; // over write the validator.evaluationfunction to new funtion if ( typeof ( this ._validator.evaluationfunction) == ' String ' ) { this ._validator.evaluationfunction = eval( this ._validator.evaluationfunction); } var evaluationfunction = this ._validator.evaluationfunction; this ._validator.evaluationfunction = function (val) { if ( ! evaluationfunction(val)) { ValidatorCallout.show(val); return false ; } else { ValidatorCallout.hide(val); return true ; } }; $( this ._validatorControl).unbind( ' focus ' , ShowErrorMessageWhenFocus) .bind( ' focus ' , ShowErrorMessageWhenFocus); } }; ValidatorCallout.show = function (validator) { if (validator.callout._validatorControl != null ) { var ctlValidator = $(validator.callout._validatorControl); ctlValidator.addClass( " error " ); var errorPopupId = validator.callout._divContainer.id; if (ctlValidator.attr( ' validator ' ) == null || ctlValidator.attr( ' validator ' ) == '' ) { ctlValidator.attr( ' validator ' , errorPopupId); } // only show the first error when multiple validator validate one control if (ctlValidator.attr( ' validator ' ) == errorPopupId) { ShowErrorMessage(ctlValidator, validator.callout._divContainer); } } } ValidatorCallout.hide = function (validator) { $(validator.callout._divContainer).css( ' display ' , ' none ' ); if (validator.callout._validatorControl != null ) { var ctlValidator = $(validator.callout._validatorControl); if (ctlValidator.attr( ' validator ' ) == validator.callout._divContainer.id) { ctlValidator.removeClass( ' error ' ); ctlValidator.removeAttr( ' validator ' ); } } } function ShowErrorMessageWhenFocus(e) { var ctlToValidate = $( this ); var messageDivId = ctlToValidate.attr( ' validator ' ); var messageDiv = $( ' # ' + messageDivId); ShowErrorMessage(ctlToValidate, messageDiv); } function ShowErrorMessage(validatorControl, messageContainer) { var ctlValidator = $(validatorControl); var position = ctlValidator.position(); position.top += ctlValidator.outerHeight( true ) - 10 ; $(messageContainer) .css({ ' width ' : ctlValidator.width() , ' left ' : position.left , ' top ' : position.top , ' display ' : ' block ' }); // setTimeout("HideObject('" +$(messageContainer).attr("id") + "');", 2500); } function HideObject(elemId) { $( ' # ' + elemId).css( ' display ' , ' none ' ); } jQuery( function ($) { if ( typeof (Page_Validators) != ' undefined ' ) { for ( var i = 0 ; i < Page_Validators.length; i ++ ) { var validatorCall = new ValidatorCallout(Page_Validators[i]); validatorCall.initiate(); } } });
要点:
jQuery( function ($) { if ( typeof (Page_Validators) != ' undefined ' ) { for ( var i = 0 ; i < Page_Validators.length; i ++ ) { var validatorCall = new ValidatorCallout(Page_Validators[i]); validatorCall.initiate(); } }});
在页面加载的时候,将 Page_Validators中的验证控件取出来创建validatorCallout,然后调用
initiate方法创建提示控件 ,将它的 evaluationfunction修改成新的包装后的方法,实现方式:
var evaluationfunction = this ._validator.evaluationfunction; this ._validator.evaluationfunction = function (val) { if ( ! evaluationfunction(val)) { ValidatorCallout.show(val); return false ; } else { ValidatorCallout.hide(val); return true ; }
};
关键方法:
initiate: 初始化控件,并创建相应的提示信息元素
show: 显示错误提示信息
hide: 隐藏错误信息
使用方法:在页面中加入JS脚本和CSS文件就可以了。(另外需要引用jQuery脚本文件)
下载:
效果大家试一下就知道了。