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::input_element::HTMLInputElement;
17use crate::dom::input_element::input_type::InputType;
18use crate::dom::node::Node;
19use crate::dom::nodelist::{NodeList, NodeListType, RadioList, RadioListMode};
20use crate::dom::window::Window;
21use crate::script_runtime::CanGc;
22
23#[dom_struct]
24pub(crate) struct RadioNodeList {
25 node_list: NodeList,
26}
27
28impl RadioNodeList {
29 #[cfg_attr(crown, expect(crown::unrooted_must_root))]
30 fn new_inherited(list_type: NodeListType) -> RadioNodeList {
31 RadioNodeList {
32 node_list: NodeList::new_inherited(list_type),
33 }
34 }
35
36 #[cfg_attr(crown, expect(crown::unrooted_must_root))]
37 pub(crate) fn new(
38 window: &Window,
39 list_type: NodeListType,
40 can_gc: CanGc,
41 ) -> DomRoot<RadioNodeList> {
42 reflect_dom_object(
43 Box::new(RadioNodeList::new_inherited(list_type)),
44 window,
45 can_gc,
46 )
47 }
48
49 pub(crate) fn new_controls_except_image_inputs(
50 window: &Window,
51 form: &HTMLFormElement,
52 name: &Atom,
53 can_gc: CanGc,
54 ) -> DomRoot<RadioNodeList> {
55 RadioNodeList::new(
56 window,
57 NodeListType::Radio(RadioList::new(
58 form,
59 RadioListMode::ControlsExceptImageInputs,
60 name.clone(),
61 )),
62 can_gc,
63 )
64 }
65
66 pub(crate) fn new_images(
67 window: &Window,
68 form: &HTMLFormElement,
69 name: &Atom,
70 can_gc: CanGc,
71 ) -> DomRoot<RadioNodeList> {
72 RadioNodeList::new(
73 window,
74 NodeListType::Radio(RadioList::new(form, RadioListMode::Images, name.clone())),
75 can_gc,
76 )
77 }
78}
79
80impl RadioNodeListMethods<crate::DomTypeHolder> for RadioNodeList {
81 fn Length(&self) -> u32 {
84 self.node_list.Length()
85 }
86
87 fn Value(&self) -> DOMString {
89 self.upcast::<NodeList>()
90 .iter()
91 .find_map(|node| {
92 node.downcast::<HTMLInputElement>().and_then(|input| {
94 if matches!(*input.input_type(), InputType::Radio(_)) && input.Checked() {
95 let value = input.Value();
97 Some(if value.is_empty() {
98 DOMString::from("on")
99 } else {
100 value
101 })
102 } else {
103 None
104 }
105 })
106 })
107 .unwrap_or(DOMString::from(""))
109 }
110
111 fn SetValue(&self, value: DOMString, can_gc: CanGc) {
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, can_gc);
122 return;
123 }
124 },
125 InputType::Radio(_) => {
126 if input.Value() == value {
128 input.SetChecked(true, can_gc);
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}