使用JavaScript进行即时表单验证

HTML5引入了一些新属性来实现基于浏览器的表单验证。 pattern属性是一个正则表达式,它定义了textarea元素和大多数input类型的有效输入范围。 required属性指定是否需要一个字段。 对于未实现这些属性的旧版浏览器,我们可以将其值用作polyfill的基础。 我们还可以使用它们来提供更有趣的增强功能-即时表单验证。

我们在这里必须非常小心,不要被迷住,创建过于激进的验证,这会破坏自然的浏览行为并妨碍人们的使用。 例如,我见过一些表格,其中不可能用Tab键离开无效字段-使用JavaScript(或滥用 )强制焦点保持在字段内,直到有效为止。 这是非常差的可用性,并且直接违反了可访问性准则 。

我们在本文中要做的是减少干扰。 它甚至不是完整的客户端验证–只是一个微妙的可用性增强,以可访问的方式实现,(正如我在测试脚本时所发现的)几乎与Firefox现在所做的相同!

基本概念

在最新版本的Firefox中,如果required字段为空或其值与pattern不匹配,则该字段将显示红色轮廓,如下图所示。

使用JavaScript进行即时表单验证_第1张图片

当然,这不会立即发生。 如果是这样,则默认情况下,每个必填字段都将具有该轮廓。 相反,这些轮廓仅您与该字段进行交互后才显示,这基本上(尽管不完全准确)类似于onchange事件。

这就是我们要做的,使用onchange作为触发事件。 或者,我们可以使用oninput事件,该事件在将任何值键入或粘贴到字段中时立即触发。 但这实在是瞬时了,因为在键入时可以很容易地连续快速地触发许多类型的开关,从而产生闪烁的效果,这会使某些用户感到烦恼或无法分散他们的注意力。 而且,无论如何, oninput不会从编程输入中触发,而onchange会触发,因此我们可能需oninput来处理第三方插件的自动完成之类的事情。

定义HTML和CSS

因此,让我们看一下我们的实现,从基于以下内容的HTML开始:

Add your comment

此示例是一个简单的注释表单,其中某些字段是必填字段,某些字段经过验证,而有些字段两者都是。 其中有场required也有aria-required ,提供回退语义辅助技术的不理解新的input类型。

ARIA规范还定义了一个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 ,坦白地说,这样看起来会更好,但是在不支持box-shadows的浏览器(例如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);
    });
  }
}

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

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

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

一旦有了这些实用程序,就可以定义主要的验证功能,该功能将测试该字段,然后执行实际的验证(如果适用):

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构造函数,这将创建一个我们可以针对该值进行测试的regex对象。 但是,我们必须预先测试该值以确保其不为空,以便正则表达式本身不必考虑空字符串。

一旦确定了一个字段是否无效,我们就可以控制其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);
    });
  }
}

结论与超越

因此,我们有了它–一种简单,非侵入式的即时表单验证增强功能,提供了可访问的视觉提示来帮助用户完成表单。 您可以在下面查看演示:

请参阅CodePen上的SitePoint ( @SitePoint )进行的笔即时表单验证 。

一旦执行了该脚本,我们实际上仅需要跳过和跳过完整的polyfill即可。 这样的脚本超出了本文的范围,但是如果您想进一步开发它,那么所有基本块都在这里–测试是否应验证字段,根据模式和/或要求验证字段以及绑定触发器事件。

我必须承认,我不确定这是否值得! 如果您已经有了此增强功能(在IE7以后的所有现代浏览器中都可以使用),并且除了实现服务器端验证之外别无选择 ,并且考虑到支持patternrequired使用浏览器的浏览器已经将它们用于预验证,提交验证–考虑到所有这些,是否真的有必要添加另一个polyfill?

From: https://www.sitepoint.com/instant-validation/

你可能感兴趣的:(使用JavaScript进行即时表单验证)