aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/dom/radionodelist.rs
diff options
context:
space:
mode:
Diffstat (limited to 'components/script/dom/radionodelist.rs')
-rw-r--r--components/script/dom/radionodelist.rs152
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)
+ }
+}