script/dom/svg/
svgelement.rs1use dom_struct::dom_struct;
6use html5ever::{LocalName, Prefix, local_name, ns};
7use js::rust::HandleObject;
8use script_bindings::str::DOMString;
9use stylo_dom::ElementState;
10
11use crate::dom::attr::Attr;
12use crate::dom::bindings::codegen::Bindings::HTMLOrSVGElementBinding::FocusOptions;
13use crate::dom::bindings::codegen::Bindings::SVGElementBinding::SVGElementMethods;
14use crate::dom::bindings::inheritance::Castable;
15use crate::dom::bindings::root::{Dom, DomRoot, MutNullableDom};
16use crate::dom::css::cssstyledeclaration::{
17 CSSModificationAccess, CSSStyleDeclaration, CSSStyleOwner,
18};
19use crate::dom::document::{Document, FocusInitiator};
20use crate::dom::element::{AttributeMutation, Element};
21use crate::dom::node::{Node, NodeTraits};
22use crate::dom::virtualmethods::VirtualMethods;
23use crate::script_runtime::CanGc;
24
25#[dom_struct]
26pub(crate) struct SVGElement {
27 element: Element,
28 style_decl: MutNullableDom<CSSStyleDeclaration>,
29}
30
31impl SVGElement {
32 fn new_inherited(
33 tag_name: LocalName,
34 prefix: Option<Prefix>,
35 document: &Document,
36 ) -> SVGElement {
37 SVGElement::new_inherited_with_state(ElementState::empty(), tag_name, prefix, document)
38 }
39
40 pub(crate) fn new_inherited_with_state(
41 state: ElementState,
42 tag_name: LocalName,
43 prefix: Option<Prefix>,
44 document: &Document,
45 ) -> SVGElement {
46 SVGElement {
47 element: Element::new_inherited_with_state(state, tag_name, ns!(svg), prefix, document),
48 style_decl: Default::default(),
49 }
50 }
51
52 pub(crate) fn new(
53 tag_name: LocalName,
54 prefix: Option<Prefix>,
55 document: &Document,
56 proto: Option<HandleObject>,
57 can_gc: CanGc,
58 ) -> DomRoot<SVGElement> {
59 Node::reflect_node_with_proto(
60 Box::new(SVGElement::new_inherited(tag_name, prefix, document)),
61 document,
62 proto,
63 can_gc,
64 )
65 }
66
67 fn as_element(&self) -> &Element {
68 self.upcast::<Element>()
69 }
70}
71
72impl VirtualMethods for SVGElement {
73 fn super_type(&self) -> Option<&dyn VirtualMethods> {
74 Some(self.as_element() 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 let element = self.as_element();
82 if let (&local_name!("nonce"), mutation) = (attr.local_name(), mutation) {
83 match mutation {
84 AttributeMutation::Set(_) => {
85 let nonce = &**attr.value();
86 element.update_nonce_internal_slot(nonce.to_owned());
87 },
88 AttributeMutation::Removed => {
89 element.update_nonce_internal_slot(String::new());
90 },
91 }
92 }
93 }
94}
95
96impl SVGElementMethods<crate::DomTypeHolder> for SVGElement {
97 fn Style(&self) -> DomRoot<CSSStyleDeclaration> {
99 self.style_decl.or_init(|| {
100 let global = self.owner_window();
101 CSSStyleDeclaration::new(
102 &global,
103 CSSStyleOwner::Element(Dom::from_ref(self.upcast())),
104 None,
105 CSSModificationAccess::ReadWrite,
106 CanGc::note(),
107 )
108 })
109 }
110
111 global_event_handlers!();
113
114 fn Nonce(&self) -> DOMString {
116 self.as_element().nonce_value().into()
117 }
118
119 fn SetNonce(&self, value: DOMString) {
121 self.as_element()
122 .update_nonce_internal_slot(value.to_string())
123 }
124
125 fn Autofocus(&self) -> bool {
127 self.element.has_attribute(&local_name!("autofocus"))
128 }
129
130 fn SetAutofocus(&self, autofocus: bool, can_gc: CanGc) {
132 self.element
133 .set_bool_attribute(&local_name!("autofocus"), autofocus, can_gc);
134 }
135
136 fn Focus(&self, options: &FocusOptions) {
138 let document = self.element.owner_document();
139 document.request_focus_with_options(
140 Some(&self.element),
141 FocusInitiator::Local,
142 FocusOptions {
143 preventScroll: options.preventScroll,
144 },
145 CanGc::note(),
146 );
147 }
148}