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