diff options
Diffstat (limited to 'components/script/dom/radionodelist.rs')
-rw-r--r-- | components/script/dom/radionodelist.rs | 152 |
1 files changed, 152 insertions, 0 deletions
diff --git a/components/script/dom/radionodelist.rs b/components/script/dom/radionodelist.rs new file mode 100644 index 00000000000..ebb9909f1d6 --- /dev/null +++ b/components/script/dom/radionodelist.rs @@ -0,0 +1,152 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +use dom::bindings::codegen::Bindings::HTMLInputElementBinding::HTMLInputElementMethods; +use dom::bindings::codegen::Bindings::NodeListBinding::NodeListMethods; +use dom::bindings::codegen::Bindings::RadioNodeListBinding; +use dom::bindings::codegen::Bindings::RadioNodeListBinding::RadioNodeListMethods; +use dom::bindings::global::GlobalRef; +use dom::bindings::inheritance::Castable; +use dom::bindings::js::Root; +use dom::bindings::reflector::reflect_dom_object; +use dom::htmlinputelement::HTMLInputElement; +use dom::node::Node; +use dom::nodelist::{NodeList, NodeListType}; +use dom::window::Window; +use util::str::DOMString; + +#[dom_struct] +pub struct RadioNodeList { + node_list: NodeList, +} + +impl RadioNodeList { + #[allow(unrooted_must_root)] + fn new_inherited(list_type: NodeListType) -> RadioNodeList { + RadioNodeList { + node_list: NodeList::new_inherited(list_type) + } + } + + #[allow(unrooted_must_root)] + pub fn new(window: &Window, list_type: NodeListType) -> Root<RadioNodeList> { + reflect_dom_object(box RadioNodeList::new_inherited(list_type), + GlobalRef::Window(window), + RadioNodeListBinding::Wrap) + } + + // FIXME: This shouldn't need to be implemented here since NodeList (the parent of + // RadioNodeList) implements Length + // https://github.com/servo/servo/issues/5875 + pub fn Length(&self) -> u32 { + self.node_list.Length() + } +} + +impl RadioNodeListMethods for RadioNodeList { + // https://html.spec.whatwg.org/multipage/#dom-radionodelist-value + fn Value(&self) -> DOMString { + match *self.upcast::<NodeList>().get_list_type() { + NodeListType::Simple(ref v) => { + v.iter().filter_map(|node| { + // Step 1 + node.downcast::<HTMLInputElement>().and_then(|input| { + match input.type_() { + atom!("radio") if input.Checked() => { + // Step 3-4 + let value = input.Value(); + Some(if value.is_empty() { DOMString::from("on") } else { value }) + } + _ => None + } + }) + }).next() + // Step 2 + .unwrap_or(DOMString::from("")) + } + NodeListType::Children(ref cl) => { + cl.get_parent_node().traverse_preorder().filter_map(|node| { + // Step 1 + node.downcast::<HTMLInputElement>().and_then(|input| { + match input.type_() { + atom!("radio") if input.Checked() => { + // Step 3-4 + let value = input.Value(); + Some(if value.is_empty() { DOMString::from("on") } else { value }) + } + _ => None + } + }) + }).next() + // Step 2 + .unwrap_or(DOMString::from("")) + } + } + } + + // https://html.spec.whatwg.org/multipage/infrastructure.html#dom-radionodelist-value + fn SetValue(&self, value: DOMString) { + match *self.upcast::<NodeList>().get_list_type() { + NodeListType::Simple(ref v) => { + for node in v.iter() { + // Step 1 + if let Some(input) = node.downcast::<HTMLInputElement>() { + match input.type_() { + atom!("radio") if value == DOMString::from("on") => { + // Step 2 + let val = input.Value(); + if val.is_empty() || val == DOMString::from("on") { + input.SetChecked(true); + return; + } + } + atom!("radio") => { + // Step 2 + if input.Value() == value { + input.SetChecked(true); + return; + } + } + _ => {} + } + } + } + } + NodeListType::Children(ref cl) => { + for node in cl.get_parent_node().traverse_preorder() { + // Step 1 + if let Some(input) = node.downcast::<HTMLInputElement>() { + match input.type_() { + atom!("radio") if value == DOMString::from("on") => { + // Step 2 + let val = input.Value(); + if val.is_empty() || val == DOMString::from("on") { + input.SetChecked(true); + return; + } + } + atom!("radio") => { + // Step 2 + if input.Value() == value { + input.SetChecked(true); + return; + } + } + _ => {} + } + } + } + } + }; + } + + // FIXME: This shouldn't need to be implemented here since NodeList (the parent of + // RadioNodeList) implements IndexedGetter. + // https://github.com/servo/servo/issues/5875 + // + // https://dom.spec.whatwg.org/#dom-nodelist-item + fn IndexedGetter(&self, index: u32, found: &mut bool) -> Option<Root<Node>> { + self.node_list.IndexedGetter(index, found) + } +} |