script/dom/html/
htmlsourceelement.rs1use dom_struct::dom_struct;
6use html5ever::{LocalName, Prefix, local_name};
7use js::context::JSContext;
8use js::rust::HandleObject;
9use style::attr::AttrValue;
10
11use crate::dom::bindings::codegen::Bindings::HTMLSourceElementBinding::HTMLSourceElementMethods;
12use crate::dom::bindings::codegen::Bindings::NodeBinding::Node_Binding::NodeMethods;
13use crate::dom::bindings::inheritance::Castable;
14use crate::dom::bindings::root::{Dom, DomRoot, Root};
15use crate::dom::bindings::str::{DOMString, USVString};
16use crate::dom::document::Document;
17use crate::dom::element::AttributeMutation;
18use crate::dom::element::attributes::storage::AttrRef;
19use crate::dom::html::htmlelement::HTMLElement;
20use crate::dom::html::htmlimageelement::HTMLImageElement;
21use crate::dom::html::htmlmediaelement::HTMLMediaElement;
22use crate::dom::html::htmlpictureelement::HTMLPictureElement;
23use crate::dom::node::{BindContext, Node, NodeDamage, UnbindContext};
24use crate::dom::virtualmethods::VirtualMethods;
25
26#[dom_struct]
27pub(crate) struct HTMLSourceElement {
28 htmlelement: HTMLElement,
29}
30
31impl HTMLSourceElement {
32 fn new_inherited(
33 local_name: LocalName,
34 prefix: Option<Prefix>,
35 document: &Document,
36 ) -> HTMLSourceElement {
37 HTMLSourceElement {
38 htmlelement: HTMLElement::new_inherited(local_name, prefix, document),
39 }
40 }
41
42 pub(crate) fn new(
43 cx: &mut js::context::JSContext,
44 local_name: LocalName,
45 prefix: Option<Prefix>,
46 document: &Document,
47 proto: Option<HandleObject>,
48 ) -> DomRoot<HTMLSourceElement> {
49 Node::reflect_node_with_proto(
50 cx,
51 Box::new(HTMLSourceElement::new_inherited(
52 local_name, prefix, document,
53 )),
54 document,
55 proto,
56 )
57 }
58
59 fn iterate_next_html_image_element_siblings(
60 next_siblings_iterator: impl Iterator<Item = Root<Dom<Node>>>,
61 callback: impl Fn(&HTMLImageElement),
62 ) {
63 for next_sibling in next_siblings_iterator {
64 if let Some(html_image_element_sibling) = next_sibling.downcast::<HTMLImageElement>() {
65 callback(html_image_element_sibling);
66 }
67 }
68 }
69
70 fn iterate_next_html_image_element_siblings_with_cx(
71 cx: &mut JSContext,
72 next_siblings_iterator: impl Iterator<Item = Root<Dom<Node>>>,
73 callback: impl Fn(&mut JSContext, &HTMLImageElement),
74 ) {
75 for next_sibling in next_siblings_iterator {
76 if let Some(html_image_element_sibling) = next_sibling.downcast::<HTMLImageElement>() {
77 callback(cx, html_image_element_sibling);
78 }
79 }
80 }
81}
82
83impl VirtualMethods for HTMLSourceElement {
84 fn super_type(&self) -> Option<&dyn VirtualMethods> {
85 Some(self.upcast::<HTMLElement>() as &dyn VirtualMethods)
86 }
87
88 fn attribute_mutated(
89 &self,
90 cx: &mut js::context::JSContext,
91 attr: AttrRef<'_>,
92 mutation: AttributeMutation,
93 ) {
94 self.super_type()
95 .unwrap()
96 .attribute_mutated(cx, attr, mutation);
97
98 match attr.local_name() {
99 &local_name!("srcset") |
100 &local_name!("sizes") |
101 &local_name!("media") |
102 &local_name!("type") => {
103 if let Some(parent) = self.upcast::<Node>().GetParentElement() &&
107 parent.is::<HTMLPictureElement>()
108 {
109 let next_sibling_iterator = self.upcast::<Node>().following_siblings();
110 HTMLSourceElement::iterate_next_html_image_element_siblings_with_cx(
111 cx,
112 next_sibling_iterator,
113 |cx, image| image.update_the_image_data(cx),
114 );
115 }
116 },
117 &local_name!("width") | &local_name!("height") => {
118 if let Some(parent) = self.upcast::<Node>().GetParentElement() &&
123 parent.is::<HTMLPictureElement>()
124 {
125 let next_sibling_iterator = self.upcast::<Node>().following_siblings();
126 HTMLSourceElement::iterate_next_html_image_element_siblings(
127 next_sibling_iterator,
128 |image| image.upcast::<Node>().dirty(NodeDamage::Other),
129 );
130 }
131 },
132 _ => {},
133 }
134 }
135
136 fn parse_plain_attribute(&self, name: &LocalName, value: DOMString) -> AttrValue {
137 match name {
138 &local_name!("width") | &local_name!("height") => {
139 AttrValue::from_dimension(value.into())
140 },
141 _ => self
142 .super_type()
143 .unwrap()
144 .parse_plain_attribute(name, value),
145 }
146 }
147
148 fn bind_to_tree(&self, cx: &mut JSContext, context: &BindContext) {
150 self.super_type().unwrap().bind_to_tree(cx, context);
151
152 let parent = self.upcast::<Node>().GetParentNode().unwrap();
154
155 if parent.is::<HTMLMediaElement>() && std::ptr::eq(&*parent, context.parent) {
158 parent
159 .downcast::<HTMLMediaElement>()
160 .unwrap()
161 .handle_source_child_insertion(self, cx);
162 }
163
164 if parent.is::<HTMLPictureElement>() && std::ptr::eq(&*parent, context.parent) {
167 let next_sibling_iterator = self.upcast::<Node>().following_siblings();
168 HTMLSourceElement::iterate_next_html_image_element_siblings_with_cx(
169 cx,
170 next_sibling_iterator,
171 |cx, image| image.update_the_image_data(cx),
172 );
173 }
174 }
175
176 fn unbind_from_tree(&self, cx: &mut js::context::JSContext, context: &UnbindContext) {
178 self.super_type().unwrap().unbind_from_tree(cx, context);
179
180 if context.parent.is::<HTMLPictureElement>() &&
183 !self.upcast::<Node>().has_parent() &&
184 let Some(next_sibling) = context.next_sibling
185 {
186 let next_sibling_iterator = next_sibling.inclusively_following_siblings();
187 HTMLSourceElement::iterate_next_html_image_element_siblings_with_cx(
188 cx,
189 next_sibling_iterator,
190 |cx, image| image.update_the_image_data(cx),
191 );
192 }
193 }
194}
195
196impl HTMLSourceElementMethods<crate::DomTypeHolder> for HTMLSourceElement {
197 make_url_getter!(Src, "src");
199
200 make_url_setter!(SetSrc, "src");
202
203 make_getter!(Type, "type");
205
206 make_setter!(SetType, "type");
208
209 make_url_getter!(Srcset, "srcset");
211
212 make_url_setter!(SetSrcset, "srcset");
214
215 make_getter!(Sizes, "sizes");
217
218 make_setter!(SetSizes, "sizes");
220
221 make_getter!(Media, "media");
223
224 make_setter!(SetMedia, "media");
226
227 make_dimension_uint_getter!(Width, "width");
229
230 make_dimension_uint_setter!(SetWidth, "width");
232
233 make_dimension_uint_getter!(Height, "height");
235
236 make_dimension_uint_setter!(SetHeight, "height");
238}