From 51f9671db2c6ccb4e8627b2340d33d8020f457b5 Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Wed, 26 Oct 2016 21:29:11 -0400 Subject: Implement "list of options" concept on `HTMLSelectElement`. Fixes https://github.com/servo/servo/issues/13763. --- components/script/dom/htmlselectelement.rs | 65 +++++++++++++++++++++--------- 1 file changed, 45 insertions(+), 20 deletions(-) (limited to 'components/script/dom/htmlselectelement.rs') diff --git a/components/script/dom/htmlselectelement.rs b/components/script/dom/htmlselectelement.rs index ad66f2b05f3..d207c86aab4 100755 --- a/components/script/dom/htmlselectelement.rs +++ b/components/script/dom/htmlselectelement.rs @@ -31,6 +31,7 @@ use dom::validation::Validatable; use dom::validitystate::{ValidityState, ValidationFlags}; use dom::virtualmethods::VirtualMethods; use html5ever_atoms::LocalName; +use std::iter; use style::attr::AttrValue; use style::element_state::*; @@ -84,10 +85,25 @@ impl HTMLSelectElement { HTMLSelectElementBinding::Wrap) } + // https://html.spec.whatwg.org/multipage/#concept-select-option-list + fn list_of_options(&self) -> impl Iterator> { + self.upcast::() + .children() + .flat_map(|node| { + if node.is::() { + let node = Root::downcast::(node).unwrap(); + Choice3::First(iter::once(node)) + } else if node.is::() { + Choice3::Second(node.children().filter_map(Root::downcast)) + } else { + Choice3::Third(iter::empty()) + } + }) + } + // https://html.spec.whatwg.org/multipage/#the-select-element:concept-form-reset-control pub fn reset(&self) { - let node = self.upcast::(); - for opt in node.traverse_preorder().filter_map(Root::downcast::) { + for opt in self.list_of_options() { opt.set_selectedness(opt.DefaultSelected()); opt.set_dirtiness(false); } @@ -103,8 +119,7 @@ impl HTMLSelectElement { let mut first_enabled: Option> = None; let mut last_selected: Option> = None; - let node = self.upcast::(); - for opt in node.traverse_preorder().filter_map(Root::downcast::) { + for opt in self.list_of_options() { if opt.Selected() { opt.set_selectedness(false); last_selected = Some(Root::from_ref(&opt)); @@ -127,11 +142,10 @@ impl HTMLSelectElement { } pub fn push_form_data(&self, data_set: &mut Vec) { - let node = self.upcast::(); if self.Name().is_empty() { return; } - for opt in node.traverse_preorder().filter_map(Root::downcast::) { + for opt in self.list_of_options() { let element = opt.upcast::(); if opt.Selected() && element.enabled_state() { data_set.push(FormDatum { @@ -146,9 +160,8 @@ impl HTMLSelectElement { // https://html.spec.whatwg.org/multipage/#concept-select-pick pub fn pick_option(&self, picked: &HTMLOptionElement) { if !self.Multiple() { - let node = self.upcast::(); let picked = picked.upcast(); - for opt in node.traverse_preorder().filter_map(Root::downcast::) { + for opt in self.list_of_options() { if opt.upcast::() != picked { opt.set_selectedness(false); } @@ -271,9 +284,7 @@ impl HTMLSelectElementMethods for HTMLSelectElement { // https://html.spec.whatwg.org/multipage/#dom-select-value fn Value(&self) -> DOMString { - self.upcast::() - .traverse_preorder() - .filter_map(Root::downcast::) + self.list_of_options() .filter(|opt_elem| opt_elem.Selected()) .map(|opt_elem| opt_elem.Value()) .next() @@ -282,9 +293,7 @@ impl HTMLSelectElementMethods for HTMLSelectElement { // https://html.spec.whatwg.org/multipage/#dom-select-value fn SetValue(&self, value: DOMString) { - let mut opt_iter = self.upcast::() - .traverse_preorder() - .filter_map(Root::downcast::); + let mut opt_iter = self.list_of_options(); // Reset until we find an