使用JavaScript进行即时表单验证

2017-07-21阅读(4321)评论(0)牵着狗狗看MM

苏州实时公交查询

HTML5引入了几个新的属性来实现基于浏览器的表单验证。 pattern属性是一个正则表达式,用于定义textarea元素和大多数input类型的有效输入范围。 required 属性表示是否必填字段。 对于不支持这些属性的传统浏览器,我们可以使用它们的值作为polyfill的基础。 我们还可以使用它们来提供更有趣的增强 – 即时表单验证。

基本概念

在最新版本的Firefox中,如果required 字段为空,或者其值与模式不匹配,那么该字段将显示一个红色的轮廓,如下图所示。

这当然不会立即发生。 如果是,则默认情况下,每个必填字段都将具有该轮廓。 相反,这些轮廓仅在您与该字段进行交互之后才会显示,这基本上类似于onchange事件。
所以这就是我们要做的,使用onchange作为触发事件。 作为替代方案,我们可以使用oninput事件,一旦任何值被输入或粘贴到该字段中即可触发。 但是这真的太瞬间,因为它可以很容易地在许多类型的瞬间触发和快速连续打字,创造一个闪烁的效果,这将是令人讨厌的或不可能分散一些用户的注意力。 而且,在任何情况下,oninput不会从程序化输入中触发,而onchange也可能需要它来处理第三方附加组件的自动完成。

定义HTML和CSS

<form action="#" method="post">
  <fieldset>

    <legend><strong>Add your comment</strong></legend>

    <p>
      <label for="author">Name <abbr title="Required">*</abbr></label>
      <input 
        aria-required="true"
        id="author"
        name="author"
        pattern="^([- \w\d\u00c0-\u024f]+)$"
        required="required"
        size="20"
        spellcheck="false"
        title="Your name (no special characters, diacritics are okay)"
        type="text"
        value="">
    </p>

    <p>
      <label for="email">Email <abbr title="Required">*</abbr></label>
      <input 
        aria-required="true"
        id="email"
        name="email"
        pattern="^(([-\w\d]+)(\.[-\w\d]+)*@([-\w\d]+)(\.[-\w\d]+)*(\.([a-zA-Z]{2,5}|[\d]{1,3})){1,2})$" 
        required="required"
        size="30"
        spellcheck="false"
        title="Your email address"
        type="email"
        value="">
    </p>

    <p>
      <label for="website">Website</label>
      <input
        id="website"
        name="website"
        pattern="^(http[s]?:\/\/)?([-\w\d]+)(\.[-\w\d]+)*(\.([a-zA-Z]{2,5}|[\d]{1,3})){1,2}(\/([-~%\.\(\)\w\d]*\/*)*(#[-\w\d]+)?)?$"
        size="30"
        spellcheck="false"
        title="Your website address"
        type="url"
        value="">
    </p>

    <p>
      <label for="text">Comment <abbr title="Required">*</abbr></label> 
      <textarea
        aria-required="true"
        cols="40"
        id="text"
        name="text"
        required="required"
        rows="10"
        spellcheck="true"
        title="Your comment"></textarea>
    </p>

  </fieldset>
  <fieldset>

    <button name="preview" type="submit">Preview</button>
    <button name="save" type="submit">Submit Comment</button>

  </fieldset>
</form>


这个例子是一个简单的评论表单,其中一些字段是必需的,一些是验证的,一些是两者都有。 带required 的字段也会带aria-required,为不了解新input类型的辅助技术提供回退语义。

ARIA specification也定义了aria-invalid属性。这就是我们将要用来指示字段何时无效(HTML5中没有等效属性)的属性。aria-invalid属性提供了可访问信息,但它也可以用作CSS钩子来应用红色轮廓:

input[aria-invalid="true"], textarea[aria-invalid="true"] {
  border: 1px solid #f00;
  box-shadow: 0 0 4px 0 #f00;
}

我们可以只使用box-shadow,而不是border,坦率地说,这看起来更好,但是我们在有些浏览器中不支持不支持盒子阴影的指示,比如IE8。

添加JavaScript代码

现在我们有静态代码,我们可以添加脚本。 我们需要做的第一件事是添加一个addEvent()函数:

function addEvent(node, type, callback) {
  if (node.addEventListener) {
    node.addEventListener(type, function(e) {
      callback(e, e.target);
    }, false);
  } else if (node.attachEvent) {
    node.attachEvent('on' + type, function(e) {
      callback(e, e.srcElement);
    });
  }
}

接下来,我们需要一个函数来确定一个给定的字段是否应该被验证,它只是测试它既不被禁用也不是只读,并且它具有pattern required 属性:

function shouldBeValidated(field) {
  return (
    !(field.getAttribute("readonly") || field.readonly) &&
    !(field.getAttribute("disabled") || field.disabled) &&
    (field.getAttribute("pattern") || field.getAttribute("required"))
  );
}

前两个条件可能看起来很冗长,但它们是必需的,因为元素的disabled readonly 属性不一定反映其属性状态。 例如,在Opera中,硬编码属性readonly="readonly"的字段对于其readonly属性仍将返回undefined(点属性仅匹配通过脚本设置的状态)。

一旦有这些实用程序,我们可以定义主验证函数,该函数测试该字段,然后执行实际验证(如果适用):

function instantValidation(field) {
  if (shouldBeValidated(field)) {
    var invalid =
      (field.getAttribute("required") && !field.value) ||
      (field.getAttribute("pattern") &&
        field.value &&
        !new RegExp(field.getAttribute("pattern")).test(field.value));
    if (!invalid && field.getAttribute("aria-invalid")) {
      field.removeAttribute("aria-invalid");
    } else if (invalid && !field.getAttribute("aria-invalid")) {
      field.setAttribute("aria-invalid", "true");
    }
  }
}

因此,如果一个字段是必需的,但没有值,或者它有一个模式和一个值,但该值与模式不匹配,则该字段无效。

由于pattern 已经定义了正则表达式的字符串形式,所以我们要做的就是将该字符串传递给RegExp构造函数,并创建一个可以对该值进行测试的正则表达式对象。 但是,我们必须预先测试该值以确保它不为空,以便正则表达式本身不必考虑空字符串。

一旦我们确定一个字段是否无效,我们就可以控制它的aria-invalid属性来指示该状态 – 将它添加到一个不具有该字段的无效字段中,或者从一个有效的字段中删除它。 简单! 最后,为了把这一切付诸实施,我们需要将验证函数绑定到一个onchange事件。 应该如下:

addEvent(document, "change", function(e, target) {
  instantValidation(target);
});

然而,onchange事件必须发泡(使用通常称为事件委托的技术),但在Internet Explorer 8和更早版本中,onchange事件不会冒泡。 我们可以选择忽略这些浏览器,但我认为这将是一个耻辱,特别是当问题如此简单的解决方法。 它只是意味着一个更复杂的代码 – 我们必须获取inputtextarea元素的集合,遍历它们,并将onchange事件单独绑定到每个字段:

var fields = [
  document.getElementsByTagName("input"),
  document.getElementsByTagName("textarea")
];
for (var a = fields.length, i = 0; i < a; i++) {
  for (var b = fields[i].length, j = 0; j < b; j++) {
    addEvent(fields[i][j], "change", function(e, target) {
      instantValidation(target);
    });
  }
}

Demo

原文:https://www.sitepoint.com/instant-validation/

赞(0)
转载请注明来源:Web前端(W3Cways.com) - Web前端学习之路 » 使用JavaScript进行即时表单验证
分享到: 更多 (0)