script/dom/
radionodelist.rs1use dom_struct::dom_struct;
6use stylo_atoms::Atom;
7
8use crate::dom::bindings::codegen::Bindings::HTMLInputElementBinding::HTMLInputElementMethods;
9use crate::dom::bindings::codegen::Bindings::NodeListBinding::NodeListMethods;
10use crate::dom::bindings::codegen::Bindings::RadioNodeListBinding::RadioNodeListMethods;
11use crate::dom::bindings::inheritance::Castable;
12use crate::dom::bindings::reflector::reflect_dom_object;
13use crate::dom::bindings::root::DomRoot;
14use crate::dom::bindings::str::DOMString;
15use crate::dom::html::htmlformelement::HTMLFormElement;
16use crate::dom::html::htmlinputelement::{HTMLInputElement, InputType};
17use crate::dom::node::Node;
18use crate::dom::nodelist::{NodeList, NodeListType, RadioList, RadioListMode};
19use crate::dom::window::Window;
20use crate::script_runtime::CanGc;
21
22#[dom_struct]
23pub(crate) struct RadioNodeList {
24 node_list: NodeList,
25}
26
27impl RadioNodeList {
28 #[cfg_attr(crown, allow(crown::unrooted_must_root))]
29 fn new_inherited(list_type: NodeListType) -> RadioNodeList {
30 RadioNodeList {
31 node_list: NodeList::new_inherited(list_type),
32 }
33 }
34
35 #[cfg_attr(crown, allow(crown::unrooted_must_root))]
36 pub(crate) fn new(
37 window: &Window,
38 list_type: NodeListType,
39 can_gc: CanGc,
40 ) -> DomRoot<RadioNodeList> {
41 reflect_dom_object(
42 Box::new(RadioNodeList::new_inherited(list_type)),
43 window,
44 can_gc,
45 )
46 }
47
48 pub(crate) fn new_controls_except_image_inputs(
49 window: &Window,
50 form: &HTMLFormElement,
51 name: &Atom,
52 can_gc: CanGc,
53 ) -> DomRoot<RadioNodeList> {
54 RadioNodeList::new(
55 window,
56 NodeListType::Radio(RadioList::new(
57 form,
58 RadioListMode::ControlsExceptImageInputs,
59 name.clone(),
60 )),
61 can_gc,
62 )
63 }
64
65 pub(crate) fn new_images(
66 window: &Window,
67 form: &HTMLFormElement,
68 name: &Atom,
69 can_gc: CanGc,
70 ) -> DomRoot<RadioNodeList> {
71 RadioNodeList::new(
72 window,
73 NodeListType::Radio(RadioList::new(form, RadioListMode::Images, name.clone())),
74 can_gc,
75 )
76 }
77}
78
79impl RadioNodeListMethods<crate::DomTypeHolder> for RadioNodeList {
80 fn Length(&self) -> u32 {
83 self.node_list.Length()
84 }
85
86 fn Value(&self) -> DOMString {
88 self.upcast::<NodeList>()
89 .iter()
90 .filter_map(|node| {
91 node.downcast::<HTMLInputElement>().and_then(|input| {
93 if input.input_type() == InputType::Radio && input.Checked() {
94 let value = input.Value();
96 Some(if value.is_empty() {
97 DOMString::from("on")
98 } else {
99 value
100 })
101 } else {
102 None
103 }
104 })
105 })
106 .next()
107 .unwrap_or(DOMString::from(""))
109 }
110
111 fn SetValue(&self, value: DOMString) {
113 for node in self.upcast::<NodeList>().iter() {
114 if let Some(input) = node.downcast::<HTMLInputElement>() {
116 match input.input_type() {
117 InputType::Radio if value == *"on" => {
118 let val = input.Value();
120 if val.is_empty() || val == value {
121 input.SetChecked(true);
122 return;
123 }
124 },
125 InputType::Radio => {
126 if input.Value() == value {
128 input.SetChecked(true);
129 return;
130 }
131 },
132 _ => {},
133 }
134 }
135 }
136 }
137
138 fn IndexedGetter(&self, index: u32) -> Option<DomRoot<Node>> {
144 self.node_list.IndexedGetter(index)
145 }
146}