script/dom/html/
htmlsourceelement.rs1use dom_struct::dom_struct;
6use html5ever::{LocalName, Prefix, local_name};
7use js::rust::HandleObject;
8use style::attr::AttrValue;
9
10use crate::dom::attr::Attr;
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::html::htmlelement::HTMLElement;
19use crate::dom::html::htmlimageelement::HTMLImageElement;
20use crate::dom::html::htmlmediaelement::HTMLMediaElement;
21use crate::dom::html::htmlpictureelement::HTMLPictureElement;
22use crate::dom::node::{BindContext, Node, NodeDamage, UnbindContext};
23use crate::dom::virtualmethods::VirtualMethods;
24use crate::script_runtime::CanGc;
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 #[cfg_attr(crown, allow(crown::unrooted_must_root))]
43 pub(crate) fn new(
44 local_name: LocalName,
45 prefix: Option<Prefix>,
46 document: &Document,
47 proto: Option<HandleObject>,
48 can_gc: CanGc,
49 ) -> DomRoot<HTMLSourceElement> {
50 Node::reflect_node_with_proto(
51 Box::new(HTMLSourceElement::new_inherited(
52 local_name, prefix, document,
53 )),
54 document,
55 proto,
56 can_gc,
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
72impl VirtualMethods for HTMLSourceElement {
73 fn super_type(&self) -> Option<&dyn VirtualMethods> {
74 Some(self.upcast::<HTMLElement>() as &dyn VirtualMethods)
75 }
76
77 fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation, can_gc: CanGc) {
78 self.super_type()
79 .unwrap()
80 .attribute_mutated(attr, mutation, can_gc);
81
82 match attr.local_name() {
83 &local_name!("srcset") |
84 &local_name!("sizes") |
85 &local_name!("media") |
86 &local_name!("type") => {
87 if let Some(parent) = self.upcast::<Node>().GetParentElement() {
91 if parent.is::<HTMLPictureElement>() {
92 let next_sibling_iterator = self.upcast::<Node>().following_siblings();
93 HTMLSourceElement::iterate_next_html_image_element_siblings(
94 next_sibling_iterator,
95 |image| image.update_the_image_data(can_gc),
96 );
97 }
98 }
99 },
100 &local_name!("width") | &local_name!("height") => {
101 if let Some(parent) = self.upcast::<Node>().GetParentElement() {
106 if parent.is::<HTMLPictureElement>() {
107 let next_sibling_iterator = self.upcast::<Node>().following_siblings();
108 HTMLSourceElement::iterate_next_html_image_element_siblings(
109 next_sibling_iterator,
110 |image| image.upcast::<Node>().dirty(NodeDamage::Other),
111 );
112 }
113 }
114 },
115 _ => {},
116 }
117 }
118
119 fn parse_plain_attribute(&self, name: &LocalName, value: DOMString) -> AttrValue {
120 match name {
121 &local_name!("width") | &local_name!("height") => {
122 AttrValue::from_dimension(value.into())
123 },
124 _ => self
125 .super_type()
126 .unwrap()
127 .parse_plain_attribute(name, value),
128 }
129 }
130
131 fn bind_to_tree(&self, context: &BindContext, can_gc: CanGc) {
133 self.super_type().unwrap().bind_to_tree(context, can_gc);
134
135 let parent = self.upcast::<Node>().GetParentNode().unwrap();
137
138 if parent.is::<HTMLMediaElement>() && std::ptr::eq(&*parent, context.parent) {
141 parent
142 .downcast::<HTMLMediaElement>()
143 .unwrap()
144 .handle_source_child_insertion(self, can_gc);
145 }
146
147 if parent.is::<HTMLPictureElement>() && std::ptr::eq(&*parent, context.parent) {
150 let next_sibling_iterator = self.upcast::<Node>().following_siblings();
151 HTMLSourceElement::iterate_next_html_image_element_siblings(
152 next_sibling_iterator,
153 |image| image.update_the_image_data(can_gc),
154 );
155 }
156 }
157
158 fn unbind_from_tree(&self, context: &UnbindContext, can_gc: CanGc) {
160 self.super_type().unwrap().unbind_from_tree(context, can_gc);
161
162 if context.parent.is::<HTMLPictureElement>() && !self.upcast::<Node>().has_parent() {
165 if let Some(next_sibling) = context.next_sibling {
166 let next_sibling_iterator = next_sibling.inclusively_following_siblings();
167 HTMLSourceElement::iterate_next_html_image_element_siblings(
168 next_sibling_iterator,
169 |image| image.update_the_image_data(can_gc),
170 );
171 }
172 }
173 }
174}
175
176impl HTMLSourceElementMethods<crate::DomTypeHolder> for HTMLSourceElement {
177 make_url_getter!(Src, "src");
179
180 make_url_setter!(SetSrc, "src");
182
183 make_getter!(Type, "type");
185
186 make_setter!(SetType, "type");
188
189 make_url_getter!(Srcset, "srcset");
191
192 make_url_setter!(SetSrcset, "srcset");
194
195 make_getter!(Sizes, "sizes");
197
198 make_setter!(SetSizes, "sizes");
200
201 make_getter!(Media, "media");
203
204 make_setter!(SetMedia, "media");
206
207 make_dimension_uint_getter!(Width, "width");
209
210 make_dimension_uint_setter!(SetWidth, "width");
212
213 make_dimension_uint_getter!(Height, "height");
215
216 make_dimension_uint_setter!(SetHeight, "height");
218}