如何填充RadioNodeList?
背景
根据 WHATWG< /a> someForm.elements
应该返回一个 HTMLFormElementsCollection
。
HTMLFormElementsCollection
返回一个 RadioNodeList
。
RadioNodeList
有特殊的 value
语义,它返回节点列表中第一个检查的单选列表的值。
这将允许如果实施的话以下答案可以工作
我天真地尝试了一个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;
}
}
}
}());
Background
As per the WHATWG someForm.elements
should return a HTMLFormElementsCollection
.
A HTMLFormElementsCollection
returns a RadioNodeList
if multiple elements share the same name.
The RadioNodeList
has special value
semantics where it returns the value of the first checked radio list in the nodelist.
This would allow the following answer to work if it were implemented
I naively attempted a polyfill that is based on host objects being well behaved (as per WebIDL), which they are clearly not.
Question
What is an alternative efficient implementation for this polyfill whilst we wait for browsers to become either RadioNodeList or WebIDL compliant?
Example Reference code
<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;
Naive attempt reference code
(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;
}
}
}
}());
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
如果您可以接受将
value
getter 固定到NodeList
上,那么以下内容应该可以工作RadioNodeList polyfill
感谢@@Esailija
If you can accept bolting the
value
getter ontoNodeList
then the following should workRadioNodeList polyfill
Credit to @@Esailija
为什么?您知道,在当今网络上的常用浏览器中,要求 ES5 和 WebIDL 会失败。您的代码需要新功能,无论是 ES5 )
Object.getOwnPropertyDescriptor
、get
/set
),并且正如您提到的 WebIDL 接口对象很好 -表现良好。HTML5 polyfill 旨在泛化,但在实现上通常会失败。这是一种有害的趋势。
不要修改其他对象。特别是宿主对象。
如果与 HTML5 定义有任何差异(确实存在),那么当第二功能测试脚本尝试检测某个对象上是否有
value
属性时,就会出现问题无线电组,然后假设标准支持。这与 HTML5 中的两步算法相去甚远。仅当
elements.length > 时,您的代码才会进行填充。 0
并且也会影响复选框(请记住,单选按钮并不是唯一具有checked
属性的元素)。您的设置器更改第一个检查的无线电的值。设置该值不应该检查具有该值的该名称的第一个未经检查的无线电吗?相反,只需编写您需要的通用函数即可。
Why? You know that requiring ES5 and WebIDL will fail in common-use browsers on the web today. Your code requires new features, both in ES5 )
Object.getOwnPropertyDescriptor
,get
/set
), and as you mentioned WebIDL interface objects being well-behaved.The HTML5 polyfill aims at generalization and generally fails at implementation. It is a harmful trend.
Don't modify other objects. Especially host objects.
If there is any variance from the HTML5 definition (and there is) there will be problems when a second feature-testing script tries to detect if there is a
value
property on a group of radios, and then assumes standard support.It's way off from the 2-step algorithm in HTML5.Your code polyfills only if
elements.length > 0
and affects checkboxes, too (keep in mind that radios aren't the only element with achecked
property). Your setter changes the value of the first checked radio. Shouldn't setting the value check the first unchecked radio of that name, having that value?Instead, write functions that are only as general as you need them to be.