Подтвердить что ты не робот

ВыбраноОпции сломаны или...?

Примечание: этот вопрос не имеет ничего общего с Knockout.js, но он относится к атрибуту selectedOptions элементов <select>. Это ссылка:

http://www.whatwg.org/specs/web-apps/current-work/multipage/the-button-element.html#dom-select-selectedoptions

Я думаю, что это хорошая функция для разработчиков Javascript. Поддержка довольно ограничена, но она все равно растет. Chrome, Opera и Safari должны уже поддерживать его.

Проблема в том, что я не могу понять, как это работает. Поведение должно быть довольно простым, давая живую коллекцию выбранных опций, но это оказывается не так. Вы можете предположить, что selectedOptions изменяется каждый раз, когда пользователь выбирает параметр, верно? Неправильно. Я подготовил тестовый пример:

http://jsfiddle.net/f39cC/5/

В этом примере Opera 11.64 всегда возвращает первое выбранное значение, независимо от того, что вы делаете после этого, в то время как у Chrome 21 dev и 19 stable есть странное поведение. Выполните следующие действия:

  • Выберите "Один" . Как на выходе, так и на консоли вы получаете "Один" , как и ожидалось.
  • Выберите "Два", используя Ctrl. В консоли вы получаете "Один, Два", выводящий его "Один" .
  • Выберите "Три". В консоли это "Один, Два, Три", выводят его "Один, Два".
  • Теперь выберите "Два". В консоли вы получаете "Два", на выходе "Два" (обратите внимание на две запятые).

Однако, если вы закомментируете строку console.log, вы всегда получите правильный вывод. Вы можете получить ожидаемое поведение как на консоли, так и на выходе, если вы замените две команды или сохраните значение в отдельной строке, как в этом:

http://jsfiddle.net/f39cC/2/

Итак, я что-то пропустил о selectedOptions? Слишком рано полагаться на это свойство, возможно, есть ошибка? Является ли console.log причиной проблемы в Chrome? Есть ли что-то, что я не знаю о HTMLCollection s?

У меня нет установленного Safari, может ли кто-нибудь проверить его поведение?

ОБНОВЛЕНИЕ 18/2/2013. Я не знаю, когда все изменилось, но как Chrome 24.0.1312.57, так и Opera 12.14, похоже, сейчас работают нормально. Firefox 18.0.2 и Internet Explorer 10 все еще должны реализовать свойство.

ОБНОВЛЕНИЕ 17/9/2013. Предварительный просмотр Firefox 24 и IE 11 должен поддерживать свойство. Это простой способ обхода Firefox и IE8-11:

Object.defineProperty(HTMLSelectElement.prototype, "selectedOptions", {
    get: (function() {
        try {
            document.querySelector(":checked");
            return function() {
                return this.querySelectorAll(":checked");
            };
        } catch (e) {
            return function() {
                if (!this.multiple) {
                    return this.selectedIndex >= 0
                            ? [this.options[this.selectedIndex]] : [];
                }
                for (var i = 0, a = []; i < this.options.length; i++)
                    if (this.options[i].selected) a.push(this.options[i]);
                return a;
            };
        }
    })()
});

Для IE8 он возвращает только Array, а не NodeList.

ОБНОВЛЕНИЕ 28/5/2014. Похоже, Firefox начал внедрять selectedOptions с r25.

4b9b3361

Ответ 1

Кажется, что проблема немного глубже, чем простая ошибка. Тот факт, что и WebKit, и Presto не смог поддерживать selectedOptions правильно, дает нам подсказку, что это зависит от того, что свойство должно быть HTMLCollection.

Теперь HTMLCollection имеет свое поведение, потому что они недействительны механизмом рендеринга, когда что-то происходит с DOM (изменение класса, удаление node и т.д.). Но свойство selected опциона не вызывает недействительность коллекции, что делает ее полностью ненадежной.

Я предполагаю, что проблема заключается в том, чтобы сделать новый образ живых коллекций недействительным, и это может быть не очень просто, поскольку это может повлиять на весь способ интерпретации и обработки DOM.

В настоящее время Chrome 21.0.1180.4 имеет свойство удалено.