2

背景

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

如果多个元素共享相同的名称,则AHTMLFormElementsCollection返回 a 。RadioNodeList

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

如果实施,这将允许以下答案起作用

天真地尝试了一个基于行为良好的主机对象(根据 WebIDL)的 polyfill,但显然它们不是。

问题

当我们等待浏览器成为 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;   
            }
        }    
    }
}());
4

2 回答 2

4

如果您可以接受将value吸气剂固定在上面NodeList,那么以下应该可以工作

RadioNodeList polyfill

感谢@@Esailija

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

于 2012-01-20T14:10:36.260 回答
4

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

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

不要修改其他对象。尤其是宿主对象。
如果与 HTML5 定义有任何差异(确实存在),那么当第二个功能测试脚本尝试检测一组无线电是否有value属性时,就会出现问题,然后假定标准支持。这与HTML5 中的两步算法。

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

相反,编写仅与您需要的一样通用的函数。

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

function setRadioValue(form, radioName, value) {
  // Delete comment, write code.
}
于 2012-09-12T17:14:54.507 回答