【问题标题】:How to polyfill RadioNodeList?如何填充 RadioNodeList?
【发布时间】:2012-02-15 01:15:26
【问题描述】:

背景

根据WHATWG someForm.elements 应该返回一个HTMLFormElementsCollection

如果多个元素同名,HTMLFormElementsCollection 将返回 RadioNodeList

RadioNodeList 具有特殊的value 语义,它返回节点列表中第一个检查的单选列表的值。

这将允许following answer to work if it were implemented

naively attempted a polyfill 是基于行为良好的主机对象(根据 WebIDL),但显然它们不是。

问题

当我们等待浏览器成为 RadioNodeList 或 WebIDL 兼容时,此 polyfill 的替代有效实现是什么?

示例参考代码

<form name="myform">
    <input type="radio" name="foo" value="10" /> foo 
    <input type="radio" name="foo" value="30" /> bar 
</form>

var myform = document.forms.myform;

var radio = myform.elements.foo;
var price = radio.value;

天真的尝试参考代码

(function () {
    var pd = Object.getOwnPropertyDescriptor(HTMLFormElement.prototype, "elements"),
        getElements = pd.get;

    pd.get = get;

    Object.defineProperty(HTMLFormElement.prototype, "elements", pd);

    function get() {
        var elements = getElements.call(this);

        if (elements.length) {
            Object.defineProperty(elements, "value", {
                get: getRadioNodeListValue,
                set: setRadioNodeListValue,
                configurable: true
            });
        }

        return elements;
    }

    function getRadioNodeListValue() {
        for (var i = 0, len = this.length; i < len; i++) {
            var el = this[i];
            if (el.checked) {
                return el.value;   
            }
        }
    }

    function setRadioNodeListValue(value) {
        for (var i = 0, len = this.length; i < len; i++) {
            var el = this[i];
            if (el.checked) {
                el.value = value;
                return;   
            }
        }    
    }
}());

【问题讨论】:

    标签: javascript polyfills


    【解决方案1】:

    如果您可以接受将 value getter 固定到 NodeList 上,那么以下应该可以工作

    RadioNodeList polyfill

    感谢@@Esailija

    你也可以将 .value 添加到 NodeList 原型中

    【讨论】:

      【解决方案2】:

      为什么?您知道,在当今 Web 上的常用浏览器中,要求 ES5 和 WebIDL 将失败。您的代码需要新功能,包括 ES5)Object.getOwnPropertyDescriptorget/set),以及您提到的 WebIDL 接口对象行为良好。

      HTML5 的 polyfill 旨在泛化,但通常无法实现。这是一种有害的趋势。

      不要修改其他对象。尤其是宿主对象。
      如果与 HTML5 定义有任何差异(确实存在),那么当 second 功能测试脚本尝试检测一组收音机上是否存在 value 属性时,将会出现问题,并且然后假定标准支持。它与 HTML5 中的两步算法相去甚远。

      您的代码仅在 elements.length &gt; 0 时填充并影响复选框(请记住,radio 不是唯一具有 checked 属性的元素)。您的 setter 更改了第一个选中单选的值。设置值不应该检查该名称的第一个未选中的无线电,具有该值吗?

      相反,编写仅在您需要时通用的函数。

      function getRadioValue(form, radioName) {
        // Delete comment, write code.
      }
      
      function setRadioValue(form, radioName, value) {
        // Delete comment, write code.
      }
      

      【讨论】:

      • 这是上乘的方法。然而,编写反映 HTML 规范特性的实用函数是很丑陋的。 polyfill 的幼稚实现存在漏洞这一事实是旁白。
      • 您还声称自己居住在旧金山,并且拥有大量关于 Web 脚本的知识。我想喝杯咖啡/午餐!
      • 当然,我不喜欢 utils 对象,但它确实是这里的最佳选择。对于表单繁重的应用程序,将这些函数分组在 FormUtils 对象上以用于此类事情(也设置 SELECT 的值和复选框输入)是有意义的。推迟编写任何以任何方式使用RadioNodeList 的代码,直到它至少可以在至少某些浏览器中测试。
      • 你的权利。我应该为此getValue(RadioList(form, radioName)) 实现功能。
      • 我想 2015 年的情况有所不同。在我们所做的项目中,我们可以放心地假设 ES5。 Thanks for the polyfill @Raynos.
      猜你喜欢
      • 2022-09-29
      • 1970-01-01
      • 2013-11-30
      • 2013-04-16
      • 1970-01-01
      • 2012-06-26
      • 2020-01-30
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多