script/dom/html/embedded_content/
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::MoveContext;
12use crate::dom::bindings::codegen::Bindings::HTMLSourceElementBinding::HTMLSourceElementMethods;
13use crate::dom::bindings::codegen::Bindings::NodeBinding::Node_Binding::NodeMethods;
14use crate::dom::bindings::inheritance::Castable;
15use crate::dom::bindings::root::{Dom, DomRoot, Root};
16use crate::dom::bindings::str::{DOMString, USVString};
17use crate::dom::document::Document;
18use crate::dom::element::AttributeMutation;
19use crate::dom::element::attributes::storage::AttrRef;
20use crate::dom::html::htmlelement::HTMLElement;
21use crate::dom::html::htmlimageelement::HTMLImageElement;
22use crate::dom::html::htmlmediaelement::HTMLMediaElement;
23use crate::dom::html::htmlpictureelement::HTMLPictureElement;
24use crate::dom::node::virtualmethods::VirtualMethods;
25use crate::dom::node::{BindContext, Node, NodeDamage, UnbindContext};
26
27#[dom_struct]
28pub(crate) struct HTMLSourceElement {
29 htmlelement: HTMLElement,
30}
31
32impl HTMLSourceElement {
33 fn new_inherited(
34 local_name: LocalName,
35 prefix: Option<Prefix>,
36 document: &Document,
37 ) -> HTMLSourceElement {
38 HTMLSourceElement {
39 htmlelement: HTMLElement::new_inherited(local_name, prefix, document),
40 }
41 }
42
43 pub(crate) fn new(
44 cx: &mut js::context::JSContext,
45 local_name: LocalName,
46 prefix: Option<Prefix>,
47 document: &Document,
48 proto: Option<HandleObject>,
49 ) -> DomRoot<HTMLSourceElement> {
50 Node::reflect_node_with_proto(
51 cx,
52 Box::new(HTMLSourceElement::new_inherited(
53 local_name, prefix, document,
54 )),
55 document,
56 proto,
57 )
58 }
59
60 fn iterate_next_html_image_element_siblings(
61 next_siblings_iterator: impl Iterator<Item = Root<Dom<Node>>>,
62 callback: impl Fn(&HTMLImageElement),
63 ) {
64 for next_sibling in next_siblings_iterator {
65 if let Some(html_image_element_sibling) = next_sibling.downcast::<HTMLImageElement>() {
66 callback(html_image_element_sibling);
67 }
68 }
69 }
70
71 fn iterate_next_html_image_element_siblings_with_cx(
72 cx: &mut JSContext,
73 next_siblings_iterator: impl Iterator<Item = Root<Dom<Node>>>,
74 callback: impl Fn(&mut JSContext, &HTMLImageElement),
75 ) {
76 for next_sibling in next_siblings_iterator {
77 if let Some(html_image_element_sibling) = next_sibling.downcast::<HTMLImageElement>() {
78 callback(cx, html_image_element_sibling);
79 }
80 }
81 }
82}
83
84impl VirtualMethods for HTMLSourceElement {
85 fn super_type(&self) -> Option<&dyn VirtualMethods> {
86 Some(self.upcast::<HTMLElement>() as &dyn VirtualMethods)
87 }
88
89 fn attribute_mutated(
90 &self,
91 cx: &mut js::context::JSContext,
92 attr: AttrRef<'_>,
93 mutation: AttributeMutation,
94 ) {
95 self.super_type()
96 .unwrap()
97 .attribute_mutated(cx, attr, mutation);
98
99 match attr.local_name() {
100 &local_name!("srcset") |
101 &local_name!("sizes") |
102 &local_name!("media") |
103 &local_name!("type") => {
104 if let Some(parent) = self.upcast::<Node>().GetParentElement() &&
108 parent.is::<HTMLPictureElement>()
109 {
110 let next_sibling_iterator = self.upcast::<Node>().following_siblings();
111 HTMLSourceElement::iterate_next_html_image_element_siblings_with_cx(
112 cx,
113 next_sibling_iterator,
114 |cx, image| image.update_the_image_data(cx),
115 );
116 }
117 },
118 &local_name!("width") | &local_name!("height") => {
119 if let Some(parent) = self.upcast::<Node>().GetParentElement() &&
124 parent.is::<HTMLPictureElement>()
125 {
126 let next_sibling_iterator = self.upcast::<Node>().following_siblings();
127 HTMLSourceElement::iterate_next_html_image_element_siblings(
128 next_sibling_iterator,
129 |image| image.upcast::<Node>().dirty(cx.no_gc(), NodeDamage::Other),
130 );
131 }
132 },
133 _ => {},
134 }
135 }
136
137 fn parse_plain_attribute(&self, name: &LocalName, value: DOMString) -> AttrValue {
138 match name {
139 &local_name!("width") | &local_name!("height") => {
140 AttrValue::from_dimension(value.into())
141 },
142 _ => self
143 .super_type()
144 .unwrap()
145 .parse_plain_attribute(name, value),
146 }
147 }
148
149 fn bind_to_tree(&self, cx: &mut JSContext, context: &BindContext) {
151 self.super_type().unwrap().bind_to_tree(cx, context);
152
153 let parent = self.upcast::<Node>().GetParentNode().unwrap();
155
156 if parent.is::<HTMLMediaElement>() && *parent == *context.parent {
159 parent
160 .downcast::<HTMLMediaElement>()
161 .unwrap()
162 .handle_source_child_insertion(cx, self);
163 }
164
165 if parent.is::<HTMLPictureElement>() && *parent == *context.parent {
168 let next_sibling_iterator = self.upcast::<Node>().following_siblings();
169 HTMLSourceElement::iterate_next_html_image_element_siblings_with_cx(
170 cx,
171 next_sibling_iterator,
172 |cx, image| image.update_the_image_data(cx),
173 );
174 }
175 }
176
177 fn moving_steps(&self, cx: &mut JSContext, context: &MoveContext) {
179 if let Some(super_type) = self.super_type() {
180 super_type.moving_steps(cx, context);
181 }
182
183 if let Some(parent) = self
187 .upcast::<Node>()
188 .GetParentNode()
189 .and_then(DomRoot::downcast::<HTMLMediaElement>)
190 {
191 parent.handle_source_child_insertion(cx, self);
192 }
193
194 if context.is_subtree_root && context.old_ancestor.is::<HTMLPictureElement>() {
198 for child in context.old_ancestor.child_elements() {
199 if let Some(image_child) = child.downcast::<HTMLImageElement>() {
200 image_child.update_the_image_data(cx);
201 }
202 }
203 }
204 }
205
206 fn unbind_from_tree(&self, cx: &mut js::context::JSContext, context: &UnbindContext) {
208 self.super_type().unwrap().unbind_from_tree(cx, context);
209
210 if context.parent.is::<HTMLPictureElement>() &&
213 let Some(next_sibling) = context.next_sibling
214 {
215 let next_sibling_iterator = next_sibling.inclusively_following_siblings();
216 HTMLSourceElement::iterate_next_html_image_element_siblings_with_cx(
217 cx,
218 next_sibling_iterator,
219 |cx, image| image.update_the_image_data(cx),
220 );
221 }
222 }
223}
224
225impl HTMLSourceElementMethods<crate::DomTypeHolder> for HTMLSourceElement {
226 make_url_getter!(Src, "src");
228
229 make_url_setter!(SetSrc, "src");
231
232 make_getter!(Type, "type");
234
235 make_setter!(SetType, "type");
237
238 make_url_getter!(Srcset, "srcset");
240
241 make_url_setter!(SetSrcset, "srcset");
243
244 make_getter!(Sizes, "sizes");
246
247 make_setter!(SetSizes, "sizes");
249
250 make_getter!(Media, "media");
252
253 make_setter!(SetMedia, "media");
255
256 make_dimension_uint_getter!(Width, "width");
258
259 make_dimension_uint_setter!(SetWidth, "width");
261
262 make_dimension_uint_getter!(Height, "height");
264
265 make_dimension_uint_setter!(SetHeight, "height");
267}