diff options
-rw-r--r-- | components/script/dom/mod.rs | 1 | ||||
-rw-r--r-- | components/script/dom/nodelist.rs | 13 | ||||
-rw-r--r-- | components/script/dom/radionodelist.rs | 152 | ||||
-rw-r--r-- | components/script/dom/webidls/HTMLFormControlsCollection.webidl | 6 | ||||
-rw-r--r-- | components/script/dom/webidls/NodeList.webidl | 5 | ||||
-rw-r--r-- | components/script/dom/webidls/RadioNodeList.webidl | 9 |
6 files changed, 175 insertions, 11 deletions
diff --git a/components/script/dom/mod.rs b/components/script/dom/mod.rs index 0a9a7217c53..56693280f2f 100644 --- a/components/script/dom/mod.rs +++ b/components/script/dom/mod.rs @@ -341,6 +341,7 @@ pub mod performance; pub mod performancetiming; pub mod processinginstruction; pub mod progressevent; +pub mod radionodelist; pub mod range; pub mod screen; pub mod servohtmlparser; diff --git a/components/script/dom/nodelist.rs b/components/script/dom/nodelist.rs index 6747ee5a948..5987b1b26f0 100644 --- a/components/script/dom/nodelist.rs +++ b/components/script/dom/nodelist.rs @@ -28,7 +28,7 @@ pub struct NodeList { impl NodeList { #[allow(unrooted_must_root)] - fn new_inherited(list_type: NodeListType) -> NodeList { + pub fn new_inherited(list_type: NodeListType) -> NodeList { NodeList { reflector_: Reflector::new(), list_type: list_type, @@ -36,8 +36,7 @@ impl NodeList { } #[allow(unrooted_must_root)] - pub fn new(window: &Window, - list_type: NodeListType) -> Root<NodeList> { + pub fn new(window: &Window, list_type: NodeListType) -> Root<NodeList> { reflect_dom_object(box NodeList::new_inherited(list_type), GlobalRef::Window(window), NodeListBinding::Wrap) } @@ -93,6 +92,10 @@ impl NodeList { panic!("called as_children_list() on a simple node list") } } + + pub fn get_list_type(&self) -> &NodeListType { + &self.list_type + } } #[derive(JSTraceable, HeapSizeOf)] @@ -114,6 +117,10 @@ impl ChildrenList { } } + pub fn get_parent_node(&self) -> &Node { + &*self.node + } + pub fn len(&self) -> u32 { self.node.children_count() } 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) + } +} diff --git a/components/script/dom/webidls/HTMLFormControlsCollection.webidl b/components/script/dom/webidls/HTMLFormControlsCollection.webidl index e7f2e84a566..c4a26c7b20c 100644 --- a/components/script/dom/webidls/HTMLFormControlsCollection.webidl +++ b/components/script/dom/webidls/HTMLFormControlsCollection.webidl @@ -8,9 +8,3 @@ interface HTMLFormControlsCollection : HTMLCollection { // inherits length and item() // getter (RadioNodeList or Element)? namedItem(DOMString name); // shadows inherited namedItem() }; - -/* -interface RadioNodeList : NodeList { - attribute DOMString value; -}; -*/ diff --git a/components/script/dom/webidls/NodeList.webidl b/components/script/dom/webidls/NodeList.webidl index 9d40e9e19cf..413a7154606 100644 --- a/components/script/dom/webidls/NodeList.webidl +++ b/components/script/dom/webidls/NodeList.webidl @@ -9,7 +9,8 @@ interface NodeList { [Pure] - readonly attribute unsigned long length; - [Pure] getter Node? item(unsigned long index); + [Pure] + readonly attribute unsigned long length; + // iterable<Node>; }; diff --git a/components/script/dom/webidls/RadioNodeList.webidl b/components/script/dom/webidls/RadioNodeList.webidl new file mode 100644 index 00000000000..d3c1ed892dc --- /dev/null +++ b/components/script/dom/webidls/RadioNodeList.webidl @@ -0,0 +1,9 @@ +/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* 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/. */ + +// https://html.spec.whatwg.org/multipage/#radionodelist +interface RadioNodeList : NodeList { + attribute DOMString value; +}; |