代码改变世界

验证控件网页代码分析之一

2010-04-14 18:06  Kevin-wang  阅读(514)  评论(0编辑  收藏  举报
摘自:http://www.cnblogs.com/yzx99/archive/2008/04/25/1170509.html
如果我们在文本框中什么都没有输入,直接点击按钮,则激发Button1的onclick事件,执行
javascript:WebForm_DoPostBackWithOptions(new WebForm_PostBackOptions("Button1", "", true, "", "", false, false))
分解开来,则是先执行
new WebForm_PostBackOptions("Button1", "", true, "", "", false, false)
再执行
WebForm_DoPostBackWithOptions(...)

W1
//设置好各个参数
function WebForm_PostBackOptions(eventTarget, eventArgument, validation, validationGroup, actionUrl, trackFocus, clientSubmit)
{
  
//事件的源是Button1
  this.eventTarget = eventTarget;
  
//事件的参数:无
  this.eventArgument = eventArgument;
  
//是否存在验证控件,要进验证:要
  this.validation = validation;
  
//?验证群组
  this.validationGroup = validationGroup;
  
//激发的网页:无
  this.actionUrl = actionUrl;
  
//
  this.trackFocus = trackFocus;
  
//是否进行客户端提交:否
  this.clientSubmit = clientSubmit;
}


//根据验证结果来提交数据
function WebForm_DoPostBackWithOptions(options)
{
  
//先假定验证的结果为“真”
  var validationResult = true;
  
//如果要验证的话
  if (options.validation)
    
//如果有Page_ClientValidate,就执行它
    if (typeof(Page_ClientValidate) == 'function')
      
//对整个页面进行验证
      validationResult = Page_ClientValidate(options.validationGroup);
  
if (validationResult)
  
{
    
//验证通过后的处理代码,这次先省略,下次分析
  }

  
//如果要进行客户端提交,则直接执行主网页中的__doPostBack方法
  if (options.clientSubmit)
    __doPostBack(options.eventTarget, options.eventArgument);
}

这里先对Page_ClientValidate(整个页面进行验证,在W2中)的子程序进行展开:
function Page_ClientValidate(validationGroup)
{
  Page_InvalidControlToBeFocused 
= null;
  
//如果这个页面不存在验证控件,则直接返回验证成功
  //Page_Validators在主网页中就进行了设置
  if (typeof(Page_Validators) == "undefined")
    
return true;
  
var i;
  
//对每一个验证控件,逐一进行验证
  for (i = 0; i < Page_Validators.length; i++)
    ValidatorValidate(Page_Validators[i], validationGroup, 
null);
  
//更新整个页面的验证状态
  ValidatorUpdateIsValid();
  
//处理分组情况?,太长,本次没用到,以后分析
  ValidationSummaryOnSubmit(validationGroup);
  
//验证通过则不阻塞提交,不通过则阻塞提交
  Page_BlockSubmit = !Page_IsValid;
  
return Page_IsValid;
}
它有调用
ValidatorValidate->(IsValidationGroupMatch, evaluationfunction==RequiredFieldValidatorEvaluateIsValid, ValidatorSetFocus, ValidatorUpdateDisplay):验证控件
ValidatorUpdateIsValid->AllValidatorsValid:更新整个页面的验证状态
ValidationSummaryOnSubmit:处理分组情况?
上面三个被调用的子程序中又以ValidatorValidate为重要,我们对它分析一下
function ValidatorValidate(val, validationGroup, event)
{
  val.isvalid 
= true;
  
if ((typeof(val.enabled) == "undefined" || val.enabled != false&& IsValidationGroupMatch(val, validationGroup))
  
//如果验证控件状态未设置,默认为激活 或者 验证控件状态为激活时,
  //并且验证控件所在的组与本次检验的组一致时
  {
    
if (typeof(val.evaluationfunction) == "function")
    
//有设置验证函数时
    {
      
//执行验证函数
      //ValidatorOnLoad时曾执行过val.evaluationfunction = RequiredFieldValidatorEvaluateIsValid;
      val.isvalid = val.evaluationfunction(val);
      
if (!val.isvalid && Page_InvalidControlToBeFocused == null &&
          
typeof(val.focusOnError) == "string" && val.focusOnError == "t")
        
//如果没检测通过 并且 出错时获焦点的控件还没有 并且 该控件允许出错时获得焦点 ?
        //设置焦点到该控件,?该子程序较长,未执行到此处,以后分析
        ValidatorSetFocus(val, event);
    }

  }

  
//更新验证控件的显示状态
  ValidatorUpdateDisplay(val);
}
它中间又调用了四个子程序(IsValidationGroupMatch, evaluationfunction==RequiredFieldValidatorEvaluateIsValid, ValidatorSetFocus, ValidatorUpdateDisplay),其中ValidatorSetFocus我们以后分析。其它三个分析如下:
//验证控件的组是不是指定的组
function IsValidationGroupMatch(control, validationGroup)
{
  
//如果指定的组没定义或为null,则不必验证,直接返回真
  if ((typeof(validationGroup) == "undefined"|| (validationGroup == null))
    
return true;
  
//获取验证控件的组,没定义默认为""
  var controlGroup = "";
  
if (typeof(control.validationGroup) == "string")
    controlGroup 
= control.validationGroup;
  
//如果相等返回真,不等返回假
  return (controlGroup == validationGroup);
}


//这是本次验证控件所指向的验证函数
//
如果待验证控件值不等于初使设定在验证控件中的值时,就OK
function RequiredFieldValidatorEvaluateIsValid(val)
{
  
//待验证控件的值==初使设定在验证控件中的值,返回为假
  //待验证控件的值!=初使设定在验证控件中的值,返回为真
  return (ValidatorTrim(ValidatorGetValue(val.controltovalidate)) != ValidatorTrim(val.initialvalue))
}

//对该子程序细化一下
//
用正则表达式删除前后空格
function ValidatorTrim(s)
{
  
//正则表达式 /^开始匹配 \s任何空白字符 *多次
  // (\S任何非空白字符 +加上 (\s+\S+)任何空白字符加上任何非空白字符 *)匹配零次或多次
  // \s*任何空白字符多次 $/结束匹配
  var m = s.match(/^\s*(\S+(\s+\S+)*)\s*$/);
  
//如果m为null则返回"",否则返回第二部分 即(\S+(\s+\S+)*)
  return (m == null? "" : m[1];
}

//获取控件(或组合控件)的值(或内容)
function ValidatorGetValue(id)
{
  
var control;
  control 
= document.getElementById(id);
  
if (typeof(control.value) == "string")
    
//如果控件值为字符串型,则可以返回了
    return control.value;
  
//否则再深入其子控件
  return ValidatorGetValueRecursive(control);
}


//获取组合控件的子控件值
function ValidatorGetValueRecursive(control)
{
  
//如果控件值为字符串型,或者 控件不是选项框并且控件的检测项为真(?)
  if (typeof(control.value) == "string" && (control.type != "radio" || control.checked == true))
    
return control.value;
  
var i, val;
  
//对该控件的各个子项进行逐个取值
  for (i = 0; i<control.childNodes.length; i++)
  
{
    
//递归调用本身
    val = ValidatorGetValueRecursive(control.childNodes[i]);
    
//当返回值不为空时,就可以结束了
    if (val != ""return val;
  }

  
return "";
}


//更新验证控件的显示状态
function ValidatorUpdateDisplay(val)
{
  
if (typeof(val.display) == "string")
  
//如果显示方式有设置的
  {
    
if (val.display == "None")
      
//设为None则不操作立即返回
      return;
    
if (val.display == "Dynamic")
    
{
      
//如果设置为动态的
      //则显示状态与验证状态一致?
      val.style.display = val.isvalid ? "none" : "inline";
      
return;
    }

  }

  
//对于还没有设置显示方式的
  if ((navigator.userAgent.indexOf("Mac"> -1&&
      (navigator.userAgent.indexOf(
"MSIE"> -1))
    val.style.display 
= "inline";
  
//显示状态与验证状态一致
  val.style.visibility = val.isvalid ? "hidden" : "visible";
}
我对这段程序还不理解,为什么设置一个显示不显示还要这么繁?

还有一个子程序是更新整个页面的验证状态:
//更新整个页面的验证状态
function ValidatorUpdateIsValid()
{
  Page_IsValid 
= AllValidatorsValid(Page_Validators);
}

//检查所有验证控件,一个未通过,就返回不通过
function AllValidatorsValid(validators)
{
  
if ((typeof(validators) != "undefined"&& (validators != null))
  
{
    
var i;
    
for (i = 0; i < validators.length; i++)
    
{
      
if (!validators[i].isvalid)
        
return false;
    }

  }

  
return true;
}

这些子程序分析完成后,最后要回到我们的按钮点击事件来,通过以上代码走一着,Page_BlockSubmit被设置为true,即阻塞网页的提交。
这时,再去主网页看,提交的代码:onsubmit="javascript:return WebForm_OnSubmit();"
function WebForm_OnSubmit()
{
  
//有验证控件的情况下
  if (typeof(ValidatorOnSubmit) == "function" && ValidatorOnSubmit() == false)     return false;
  
return true;
}

function ValidatorOnSubmit()
{
  
if (Page_ValidationActive)
    
//有验证控件的情况下
    return ValidatorCommonOnSubmit();
  
else
    
return true;
}

//返回页面阻塞提交的相反值,并把页面阻塞状态清空
function ValidatorCommonOnSubmit()
{
  Page_InvalidControlToBeFocused 
= null;
  
var result = !Page_BlockSubmit;
  
if ((typeof(window.event) != "undefined"&& (window.event != null))
    window.event.returnValue 
= result;
  Page_BlockSubmit 
= false;
  
return result;
}
最后结果是:当输入框不满足验证控件的要求时,验证控件显示出来,网页阻止提交。