• Asp.net Validator Control在Client Side的实现


    研究了一下Asp.net Validator Control在Client Side的实现:

    1. Page 在 Browser load完后会依次执行:
     1) var Page_Validators =  new Array(document.getElementById("RequiredFieldValidator1"), ...);
         var Page_ValidationSummaries =  new Array(document.getElementById("ValidationSummary1"));
     2) validator = document.all ? document.all["RequiredFieldValidator1"] : document.getElementById("RequiredFieldValidator1");
        .controltovalidate = "TextBox1";
        .focusOnError = "t";
        .errormessage = "Required";
        .display = "Dynamic";
        .evaluationfunction = "RequiredFieldValidatorEvaluateIsValid";
        .clientvalidationfunction = "validateTA";
        .initialvalue = "";
        .maximumvalue = "100";
        .minimumvalue = "1";
        .controltocompare = "TextBox3";
        .validationexpression = "testGP";
        .validationGroup = "^\\d{3}$";

    注意: 这里的validator仅仅是页面众多的验证控件之一(即页面会初始化很多的这么个些validator),这里列举仅作为一个实例来研究。另外,以上列举中的附加属性,是合计所有验证控件常见的属性,而不是每个validator都有以上全部属性(更准确说,每个validator仅拥有其中的不同部分)。
     3) var Page_ValidationActive = false;
     4) call ValidatorOnLoad()
        --> val:
        .evaluationfunction
        .isvalid
        .enabled
        .controltovalidate *   
        .controlhookup    *
        --> Page_ValidationActive = true;


    2. 跟踪Page中执行的ValidatorOnLoad方法到Asp.net动态生成的Resource文件(Resource1),依次会执行:
     ValidatorOnLoad(): 
        --> ValidatorHookupControlID(val.controltovalidate, val) / ValidatorHookupControlID(val.controlhookup, val)
          --> ValidatorHookupControl(ctrl, val)
            --> ValidatorHookupEvent(control, eventType, functionPrefix)
                 *** ValidatedControlOnBlur(event) <--> Page_InvalidControlToBeFocused
                 *** ValidatorOnChange(event)  <--> ValidatorValidate(vals[i], null, event) * + ValidatorUpdateIsValid() *
                 *** ValidatedTextBoxOnKeyPress(event) <--> ValidatorOnChange(event) + AllValidatorsValid(vals) *
     
     ValidatorValidate(val, validationGroup, event):
        --> IsValidationGroupMatch(val, validationGroup);
        --> val.isvalid = val.evaluationfunction(val);
                     <--> RequiredFieldValidatorEvaluateIsValid
                     <--> RangeValidatorEvaluateIsValid
                     <--> RegularExpressionValidatorEvaluateIsValid
                     <--> CompareValidatorEvaluateIsValid
                     <--> CustomValidatorEvaluateIsValid
        --> Page_InvalidControlToBeFocused == null ?
        --> ValidatorSetFocus(val, event); *
        --> ValidatorUpdateDisplay(val); *
     ValidatorUpdateIsValid():
        --> Page_IsValid = AllValidatorsValid(Page_Validators);
     AllValidatorsValid(validators):
        --> return true/false;

     IsValidationGroupMatch(control, validationGroup):
        --> return (controlGroup == validationGroup);
     ValidatorSetFocus(val, event):
        --> IsInVisibleContainer(ctrl) ?
        --> ctrl.focus() + Page_InvalidControlToBeFocused = ctrl;
     ValidatorUpdateDisplay(val):
        --> val.style.display = val.isvalid ? "none" : "inline";
        --> val.style.visibility = val.isvalid ? "hidden" : "visible";

     RequiredFieldValidatorEvaluateIsValid(val):
        --> return (ValidatorTrim(ValidatorGetValue(val.controltovalidate)) != ValidatorTrim(val.initialvalue)) *
     RangeValidatorEvaluateIsValid(val):
        --> value = ValidatorGetValue(val.controltovalidate);
        --> ValidatorTrim(value);
        --> ValidatorCompare(value, val.minimumvalue, "GreaterThanEqual", val) && ValidatorCompare(value, val.maximumvalue, "LessThanEqual", val)
     RegularExpressionValidatorEvaluateIsValid(val):
        --> value = ValidatorGetValue(val.controltovalidate);
        --> ValidatorTrim(value);
        --> rx = new RegExp(val.validationexpression);
        --> matches = rx.exec(value);
     CompareValidatorEvaluateIsValid(val):
        --> value = ValidatorGetValue(val.controltovalidate);
        --> ValidatorTrim(value);
        --> ValidatorCompare(value, compareTo, operator, val);
     CustomValidatorEvaluateIsValid(val):
        --> value = ValidatorGetValue(val.controltovalidate);
        --> eval(val.clientvalidationfunction + "(val, args) ;");
        --> return args.IsValid;

     ValidatorTrim(s):
        --> var m = s.match(/^\s*(\S+(\s+\S+)*)\s*$/);
        --> return (m == null) ? "" : m[1];
     ValidatorGetValue(id):
        --> return control.value;
        --> return ValidatorGetValueRecursive(control); *
     ValidatorCompare(operand1, operand2, operator, val):
        --> ValidatorConvert(operand1, dataType, val) *
        --> return op1 !<>= op2;

     ValidatorGetValueRecursive(control):
        --> return control.value;
        --> return val = ValidatorGetValueRecursive(control.childNodes[i]);
     ValidatorConvert(op, dataType, val):
        --> dataType == "Integer/Double/Currency/Date" ?
        --> return (isNaN(num) ? null : num); (*)

    注意:以上2部分仅仅是页面加载过程中,通过js为页面中的control和validator建立关联,并且绑定相关client event,而没有做任何validation。


    3. 回到页面源码,查看页面剩下的重要部分:
     1) <form name="form1" method="post" action="default2.aspx" onsubmit="javascript:return WebForm_OnSubmit();" id="form1">
     2) var theForm = document.forms['form1'] ? document.forms['form1'] : document.form1;
     3) <input type="submit" name="btnOK" value="submit" onclick="javascript:WebForm_DoPostBackWithOptions(new WebForm_PostBackOptions("btnOK", "", true, "testGP", "", false, false))" id="btnOK" />

     4)function __doPostBack(eventTarget, eventArgument) {
          if (!theForm.onsubmit || (theForm.onsubmit() != false)) {
              theForm.__EVENTTARGET.value = eventTarget;
              theForm.__EVENTARGUMENT.value = eventArgument;
              theForm.submit();
          }
     }
     function WebForm_OnSubmit() {
      if (typeof(ValidatorOnSubmit) == "function" && ValidatorOnSubmit() == false) return false;
      return true;
     }
     function ValidatorOnSubmit() {
          if (Page_ValidationActive) {
              return ValidatorCommonOnSubmit();
          }
          else {
              return true;
          }
     }
    从3)中input(1个button)的以下部分开始跟踪,依次执行:

    onclick="javascript:WebForm_DoPostBackWithOptions(new WebForm_PostBackOptions("btnOK", "", true, "testGP", "", false, false))" -->
     WebForm_DoPostBackWithOptions(options):
        --> WebForm_PostBackOptions options; *
        --> validationResult = Page_ClientValidate(options.validationGroup); [*--> Resource1]
        --> theForm.action = options.actionUrl;
        --> lastFocus = theForm.elements["__LASTFOCUS"]; [?]
           lastFocus.value = options.eventTarget / active.id / active.name;
        --> __doPostBack(options.eventTarget, options.eventArgument); 
     WebForm_PostBackOptions(eventTarget, eventArgument, validation, validationGroup, actionUrl, trackFocus, clientSubmit):
        --> this.eventTarget = eventTarget;
        --> ...

     Page_ClientValidate(validationGroup):
        --> Page_InvalidControlToBeFocused = null;
        --> ValidatorValidate
        --> ValidatorUpdateIsValid
        --> ValidationSummaryOnSubmit(validationGroup); *
        --> Page_BlockSubmit = !Page_IsValid;
        --> return Page_IsValid;
     ValidationSummaryOnSubmit(validationGroup):
        --> Page_ValidationSummaries
        --> Page_IsValid
        --> IsValidationGroupMatch
        --> summary.displaymode == "List/BulletList/SingleParagraph"

    可以看到,如果点击button,validators如果发现invalid部分,显示相关invalid messages。然后执行form的submit方法。跟踪

    onsubmit="javascript:return WebForm_OnSubmit();" 依次执行:

     WebForm_OnSubmit():
        --> return ValidatorOnSubmit();
        --> Page_ValidationActive
        --> ValidatorCommonOnSubmit(); * 
     ValidatorCommonOnSubmit():
        --> Page_InvalidControlToBeFocused = null;
        --> result = !Page_BlockSubmit;   *******<Page_BlockSubmit>********
        --> window.event.returnValue = result;
        --> Page_BlockSubmit = false;

    从上可以看到:form根据validators判断结果的另外一个全局变量Page_BlockSubmit来做一些事情,取消页面提交。如果页面IsValid,会执行__doPostBack方法,相关参数也被PostBack到Server Side,一个新的Asp.net生命周期就会开始(这是Server端的事情了,不再详叙)。

    附件:https://files.cnblogs.com/Langzi127/Asp.netValidator.zip

  • 相关阅读:
    Nhibernate对应关系参数介绍
    jquery mobile 登陆后页面验证
    jquery mobile radio,checkbox button 样式设置
    jquery mobile button样式设置
    Ext 三级联动 及附值
    store操作
    Javascript中try finally的细微差别
    mysql entity framework生成画面崩溃
    PYTHON推导生成
    PYTHON修饰器
  • 原文地址:https://www.cnblogs.com/Langzi127/p/1639827.html
Copyright © 2020-2023  润新知