虽然现在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;
}
// 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();
}
}
});
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();
}
}
});
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;
}
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脚本文件)
效果大家试一下就知道了。