script/dom/html/
htmlsourceelement.rs

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
5use dom_struct::dom_struct;
6use html5ever::{LocalName, Prefix, local_name};
7use js::rust::HandleObject;
8
9use crate::dom::attr::Attr;
10use crate::dom::bindings::codegen::Bindings::HTMLSourceElementBinding::HTMLSourceElementMethods;
11use crate::dom::bindings::codegen::Bindings::NodeBinding::Node_Binding::NodeMethods;
12use crate::dom::bindings::inheritance::Castable;
13use crate::dom::bindings::root::{Dom, DomRoot, Root};
14use crate::dom::bindings::str::{DOMString, USVString};
15use crate::dom::document::Document;
16use crate::dom::element::AttributeMutation;
17use crate::dom::html::htmlelement::HTMLElement;
18use crate::dom::html::htmlimageelement::HTMLImageElement;
19use crate::dom::html::htmlmediaelement::HTMLMediaElement;
20use crate::dom::node::{BindContext, Node, UnbindContext};
21use crate::dom::virtualmethods::VirtualMethods;
22use crate::script_runtime::CanGc;
23
24#[dom_struct]
25pub(crate) struct HTMLSourceElement {
26    htmlelement: HTMLElement,
27}
28
29impl HTMLSourceElement {
30    fn new_inherited(
31        local_name: LocalName,
32        prefix: Option<Prefix>,
33        document: &Document,
34    ) -> HTMLSourceElement {
35        HTMLSourceElement {
36            htmlelement: HTMLElement::new_inherited(local_name, prefix, document),
37        }
38    }
39
40    #[cfg_attr(crown, allow(crown::unrooted_must_root))]
41    pub(crate) fn new(
42        local_name: LocalName,
43        prefix: Option<Prefix>,
44        document: &Document,
45        proto: Option<HandleObject>,
46        can_gc: CanGc,
47    ) -> DomRoot<HTMLSourceElement> {
48        Node::reflect_node_with_proto(
49            Box::new(HTMLSourceElement::new_inherited(
50                local_name, prefix, document,
51            )),
52            document,
53            proto,
54            can_gc,
55        )
56    }
57
58    fn iterate_next_html_image_element_siblings(
59        next_siblings_iterator: impl Iterator<Item = Root<Dom<Node>>>,
60        can_gc: CanGc,
61    ) {
62        for next_sibling in next_siblings_iterator {
63            if let Some(html_image_element_sibling) = next_sibling.downcast::<HTMLImageElement>() {
64                html_image_element_sibling.update_the_image_data(can_gc);
65            }
66        }
67    }
68}
69
70impl VirtualMethods for HTMLSourceElement {
71    fn super_type(&self) -> Option<&dyn VirtualMethods> {
72        Some(self.upcast::<HTMLElement>() as &dyn VirtualMethods)
73    }
74
75    fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation, can_gc: CanGc) {
76        self.super_type()
77            .unwrap()
78            .attribute_mutated(attr, mutation, can_gc);
79        match attr.local_name() {
80            &local_name!("srcset") |
81            &local_name!("sizes") |
82            &local_name!("media") |
83            &local_name!("type") => {
84                let next_sibling_iterator = self.upcast::<Node>().following_siblings();
85                HTMLSourceElement::iterate_next_html_image_element_siblings(
86                    next_sibling_iterator,
87                    CanGc::note(),
88                );
89            },
90            _ => {},
91        }
92    }
93
94    /// <https://html.spec.whatwg.org/multipage/#the-source-element:nodes-are-inserted>
95    fn bind_to_tree(&self, context: &BindContext, can_gc: CanGc) {
96        self.super_type().unwrap().bind_to_tree(context, can_gc);
97        let parent = self.upcast::<Node>().GetParentNode().unwrap();
98        if let Some(media) = parent.downcast::<HTMLMediaElement>() {
99            media.handle_source_child_insertion(CanGc::note());
100        }
101        let next_sibling_iterator = self.upcast::<Node>().following_siblings();
102        HTMLSourceElement::iterate_next_html_image_element_siblings(
103            next_sibling_iterator,
104            CanGc::note(),
105        );
106    }
107
108    fn unbind_from_tree(&self, context: &UnbindContext, can_gc: CanGc) {
109        self.super_type().unwrap().unbind_from_tree(context, can_gc);
110        if let Some(next_sibling) = context.next_sibling {
111            let next_sibling_iterator = next_sibling.inclusively_following_siblings();
112            HTMLSourceElement::iterate_next_html_image_element_siblings(
113                next_sibling_iterator,
114                CanGc::note(),
115            );
116        }
117    }
118}
119
120impl HTMLSourceElementMethods<crate::DomTypeHolder> for HTMLSourceElement {
121    // https://html.spec.whatwg.org/multipage/#dom-source-src
122    make_url_getter!(Src, "src");
123
124    // https://html.spec.whatwg.org/multipage/#dom-source-src
125    make_url_setter!(SetSrc, "src");
126
127    // https://html.spec.whatwg.org/multipage/#dom-source-type
128    make_getter!(Type, "type");
129
130    // https://html.spec.whatwg.org/multipage/#dom-source-type
131    make_setter!(SetType, "type");
132
133    // https://html.spec.whatwg.org/multipage/#dom-source-srcset
134    make_url_getter!(Srcset, "srcset");
135
136    // https://html.spec.whatwg.org/multipage/#dom-source-srcset
137    make_url_setter!(SetSrcset, "srcset");
138
139    // https://html.spec.whatwg.org/multipage/#dom-source-sizes
140    make_getter!(Sizes, "sizes");
141
142    // https://html.spec.whatwg.org/multipage/#dom-source-sizes
143    make_setter!(SetSizes, "sizes");
144
145    // https://html.spec.whatwg.org/multipage/#dom-source-media
146    make_getter!(Media, "media");
147
148    // https://html.spec.whatwg.org/multipage/#dom-source-media
149    make_setter!(SetMedia, "media");
150}