Как заполнить RadioNodeList? - PullRequest
       6

Как заполнить RadioNodeList?

2 голосов
/ 20 января 2012

Фон

Согласно WHATWG someForm.elements должен возвращать HTMLFormElementsCollection.

A HTMLFormElementsCollection возвращает RadioNodeList, если несколько элементов имеют одно и то же имя.

RadioNodeList имеет специальную семантику value, в которой он возвращает значение первого проверенного списка радиоканалов в списке узлов.

Это позволит следующему ответу работать, если он будет реализован

Я наивно попытался выполнить полифил , основанный на хорошем поведении хост-объектов (согласно WebIDL), которым они явно не являются.

Вопрос

Какова альтернативная эффективная реализация этого полизаполнения, пока мы ждем, пока браузеры станут совместимыми с RadioNodeList или WebIDL?

Пример Ссылочный код

<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;   
            }
        }    
    }
}());

Ответы [ 2 ]

4 голосов
/ 12 сентября 2012

Почему? Вы знаете, что сегодня требуются ES5 и WebIDL в браузерах общего пользования в Интернете. Для вашего кода требуются новые функции, как в ES5) Object.getOwnPropertyDescriptor, get / set), так и в качестве упомянутых вами объектов интерфейса WebIDL с хорошим поведением.

Полифилл HTML5 направлен на обобщение и, как правило, не реализуется. Это вредная тенденция.

Не изменяйте другие объекты. Особенно хост-объекты.
Если есть какое-либо отклонение от определения HTML5 (и оно есть), возникнут проблемы, когда второй скрипт тестирования возможностей попытается определить, есть ли свойство value в группе радиостанций, а затем предполагает стандартную поддержку. Это далеко от двухэтапного алгоритма в HTML5.

Ваш код заполняется только в том случае, если elements.length > 0, и также влияет на флажки (имейте в виду, что радио - не единственный элемент со свойством checked). Ваш сеттер изменяет значение первого проверенного радио. Разве установка значения не должна проверять первое непроверенное радио с этим именем, имеющее это значение?

Вместо этого, напишите функции, которые являются настолько общими, насколько вам нужно.

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

function setRadioValue(form, radioName, value) {
  // Delete comment, write code.
}
4 голосов
/ 20 января 2012

Если вы можете принять привинчивание value геттера к NodeList, то следующее должно работать

Полифилл RadioNodeList

Кредит @@ Esailija

Вы также можете просто добавить .value к прототипу NodeList

...