HTML5中处理隐藏表单控件是否具有意义?

30

HTML5提供了更好地定义客户端表单验证的能力,而无需使用JavaScript。这个概念已经存在于像“maxlength”和“minlength”这样的属性中。它已经通过属性如“required”和“pattern”进行扩展。然而,HTML5也对这些属性进行了限制,WebKit浏览器已经实现了这些限制(Firefox和Opera可能也不远了)。

所谓的限制涉及到当表单控件被CSS/JavaScript隐藏时,使用"display: none"或"visibility: hidden"的CSS规则。这些限制定义为:

4.10.7.1.1 隐藏状态

当一个元素的type属性处于隐藏状态[...],元素代表一个不打算由用户检查或操作的值。

[同时,]

  • value IDL属性适用于此元素,并且处于默认模式。
  • 以下内容属性不得指定,并且不适用于该元素:acceptaltautocompletecheckeddirnameformactionformenctypeformmethodformnovalidateformtargetheightlistmaxmaxlengthminmultiplepatternplaceholderreadonlyrequiredsizesrcstepwidth
  • 以下 IDL 属性和方法不适用于该元素:checkedfileslistselectedOptionselectionStartselectionEndselectionDirectionvalueAsDatevalueAsNumber IDL 属性;select()setSelectionRange()stepDown()stepUp() 方法。
  • inputchange 事件不适用。
乍一看,似乎没有必要对用户无法控制的表单控件进行验证。对于使用默认表单控件元素构建的表单来说,这是有道理的。但现在,使用远程表单控件出现了问题。
HTML5 和 CSS3(以及主流浏览器)并没有让样式化表单控件变得更加容易。<select> 元素在样式上仍然受到极大限制,而且 <input><button> 元素具有非常不同的样式规则(对于非 IE 浏览器,几乎不可能使用 CSS 进行浏览器定位)。因此,当我的设计师需要“漂亮”的表单控件时,他们可能需要使用 HTML、CSS 和 JavaScript 重新构建这些控件。模拟的控件将远程控制由 CSS 隐藏的真实控件。对于我来说,这适用于 <select><input type="checkbox"><input type="radio"> 元素,在添加 required 属性时会在 WebKit 浏览器中引起问题。

由于HTML5规范指定,某些属性(如required)不能存在于隐藏的表单控件上,因此浏览器将需要响应无效属性。 WebKit浏览器通过根本不提交表单(而不触发JavaScript的submit事件),做出了回应。 我目前正在使用<select>元素遇到这个错误。

Chrome会在控制台中出现以下错误:

具有名称='element-name'的无效表单控件无法聚焦。

Safari则在窗口底部显示灰色条,并显示以下消息:

请在列表中选择一个项目


因此,我的关注点是HTML5是否过于严格,或者我是否处理此问题的方式不正确。它可能是以下两种情况之一:

  1. HTML5规范有缺陷并添加了另一个没有其他解决方案的限制。HTML5假定如果表单控件不可见,则用户不应该能够与其交互。这使开发人员无法利用HTML5的验证属性来控制我们远程控制的元素,同时将原始表单控件保持隐藏。我们仍然无法仅使用CSS创建自定义控件,需要自己构建它们。
  2. 我处理远程表单控件不当。由于我使用了一种“旧”技术来解决一个可能已被重新定义的问题,所以我的方法可能已经过时。也有可能,由于目前只有WebKit处理此限制,WebKit具有我尚未发现的解决方法。

目前我能想到的唯一解决方法是:

  • 每当我使用JavaScript动态隐藏表单控件时,删除受限属性,这意味着我将牺牲HTML5的验证功能。
  • 临时显示并立即隐藏有问题的表单控件,但我不确定何时执行此操作,因为从未触发submit事件,而且提交按钮上也可能没有click事件。
  • 使用novalidate属性,尽管我仍然会失去HTML5验证。
  • 所以我是看对了还是漏掉了什么?


    这不是一个非常有帮助的答案,但我建议您要么不同意实现那些无法通过CSS实现的表单控件设计,要么不要在隐藏字段上使用HTML5的验证属性。 - Paul D. Waite
    @PaulD 我认为这不应该是一个必须做出的选择。HTML5花费了很长时间,因为它必须被定义为与当前网络状态相匹配。在这种情况下,我们被迫要么放弃自定义表单控件,要么回到HTML4表单处理。无论哪种方式,我们都没有推动网络向前发展。 - KOVIKO
    你并不是真的被“迫返回”,对吧?如果你使用隐藏表单字段,你只是无法利用HTML5的验证属性。考虑到你已经通过JavaScript重新创建了HTML内置的表单字段,这只是其中的另一部分。 - Paul D. Waite
    1个回答

    25
    首先,你混淆了两件事情。如果HTML5规范中提到隐藏状态,那么规范仅指type属性设置为"value=hidden"的输入元素。在这种情况下,该输入不会被验证,也就是说,该输入不能无效。浏览器也不会中止表单提交。
    你的问题是另一个问题。你有一个真正的无效元素,它只是通过(display: none)被视觉上隐藏,并被另一个元素(或一组其他元素)替换。在你的情况下,问题在于:按照规范,在交互式表单验证的情况下,浏览器必须将焦点放在第一个无效元素上,并至少为该元素显示一个验证消息。
    问题在于浏览器既不能将焦点放在隐藏的元素上,也不能在此元素下方显示验证消息。这意味着浏览器停止了表单提交,但却有奇怪的UI来显示验证问题。
    现在回答你的问题:这有意义吗?有!如果你更改表单元素的UI,你还必须实现验证消息的UI。(如果您想自定义某些内容,则必须自定义您想要使用的所有内容)。HTML5为此提供了API。
    你需要绑定选择元素的无效事件,然后防止默认操作(如果是表单的第一个无效事件),并将你自己的验证工具提示放置在样式化的选择元素上。
    在我的HTML5表单polyfill(webshims库)中,我已经使用代码将一个本地元素(具有API)与另一个元素链接起来,并生成简单的验证工具提示。
    我创建了一个简单的jsfiddle,模拟了一个下拉框替代品,并展示了如何使用自定义表单控件实现HTML5表单验证。你可以在下面找到这个例子

    HTML

    <form class="example">
        <div>
            <select name="test" required>
                <option value="">empty </option>
                <option>sdadsa</option>
            </select>
        </div>
    
        <div>
            <input type="submit" />
        </div>
    </form>
    
    <p><a href="http://afarkas.github.com/webshim/demos/index.html" target="_blank">uses the webhsims library</a>
    

    JavaScript

    (function() {
        "use strict";
        webshims.polyfill('forms dom-support');
    
        $(function() {
            $('select').each(function(){
                var visualReplacement = $('<span tabinde="0">replaced select</select>');
                $(this).after(visualReplacement).hide();
                // Bind the visual element to the API element
                webshims.addShadowDom(this, visualReplacement);
            });
            $('form').on('firstinvalid', function(e){
                webshims.validityAlert.showFor(e.target);
                // Remove native validation
                return false;
            });
        });
    })();
    

    啊,我看错了。这会使它成为浏览器问题而不是规范问题吗?此外,虽然您提供的精彩示例基本上正是我想要的,但它并没有提供防止“提交”事件触发的(理论上的)速度增加。 - KOVIKO
    你能否解释一下,“另外,虽然你提供的很棒的例子基本上正是我想要的,但它并没有提供(理论上的)速度增加,即防止提交事件从未触发”的意思。我的英语不太好。 - alexander farkas
    基本上,您的代码使用JavaScript模拟HTML5功能,这意味着submit事件在验证之前触发,而不是相反。跳过JavaScript并使用浏览器级别的验证可能更快。 - KOVIKO
    哦,看来我低估了你的代码。我会好好看看并开始实现它。顺便说一句,我喜欢你的工作。继续加油! - KOVIKO
    如果有其他人在这里寻找创建自己的shadowdom元素的方法,那么这个答案中的示例可能出了些问题,但是这个由Alexander Farkas提供的示例可以正常工作:http://jsfiddle.net/trixta/Artst/ - Ruben
    显示剩余3条评论

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接