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 bee either RadioNodeList or WebIDL pliant?
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;
}
}
}
}());
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 bee either RadioNodeList or WebIDL pliant?
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;
}
}
}
}());
Share
Improve this question
edited May 23, 2017 at 10:24
CommunityBot
11 silver badge
asked Jan 20, 2012 at 13:14
RaynosRaynos
170k57 gold badges357 silver badges398 bronze badges
2 Answers
Reset to default 4If you can accept bolting the value
getter onto NodeList
then the following should work
RadioNodeList polyfill
Credit to @@Esailija
you could also just add .value to NodeList prototype
Why? You know that requiring ES5 and WebIDL will fail in mon-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 a checked
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.
function getRadioValue(form, radioName) {
// Delete ment, write code.
}
function setRadioValue(form, radioName, value) {
// Delete ment, write code.
}