Skip to main content

script/dom/html/document_metadata/
htmltitleelement.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 std::cell::Cell;
6
7use dom_struct::dom_struct;
8use html5ever::{LocalName, Prefix};
9use js::context::JSContext;
10use js::rust::HandleObject;
11
12use crate::dom::ElementCreator;
13use crate::dom::bindings::codegen::Bindings::HTMLTitleElementBinding::HTMLTitleElementMethods;
14use crate::dom::bindings::inheritance::Castable;
15use crate::dom::bindings::root::DomRoot;
16use crate::dom::bindings::str::DOMString;
17use crate::dom::document::Document;
18use crate::dom::html::htmlelement::HTMLElement;
19use crate::dom::node::virtualmethods::VirtualMethods;
20use crate::dom::node::{BindContext, ChildrenMutation, Node};
21
22#[dom_struct]
23pub(crate) struct HTMLTitleElement {
24    htmlelement: HTMLElement,
25    /// Whether this element is on the HTML parsers stack of open elements.
26    ///
27    /// While this is the case  we don't bother incrementally
28    /// updating the document title.
29    is_currently_being_parsed: Cell<bool>,
30}
31
32impl HTMLTitleElement {
33    fn new_inherited(
34        local_name: LocalName,
35        prefix: Option<Prefix>,
36        document: &Document,
37        is_parser_created: bool,
38    ) -> HTMLTitleElement {
39        HTMLTitleElement {
40            htmlelement: HTMLElement::new_inherited(local_name, prefix, document),
41            is_currently_being_parsed: Cell::new(is_parser_created),
42        }
43    }
44
45    pub(crate) fn new(
46        cx: &mut js::context::JSContext,
47        local_name: LocalName,
48        prefix: Option<Prefix>,
49        document: &Document,
50        proto: Option<HandleObject>,
51        creator: ElementCreator,
52    ) -> DomRoot<HTMLTitleElement> {
53        Node::reflect_node_with_proto(
54            cx,
55            Box::new(HTMLTitleElement::new_inherited(
56                local_name,
57                prefix,
58                document,
59                creator.is_parser_created(),
60            )),
61            document,
62            proto,
63        )
64    }
65
66    fn notify_title_changed(&self) {
67        let node = self.upcast::<Node>();
68        if node.is_in_a_document_tree() {
69            node.owner_doc().title_changed();
70        }
71    }
72}
73
74impl HTMLTitleElementMethods<crate::DomTypeHolder> for HTMLTitleElement {
75    /// <https://html.spec.whatwg.org/multipage/#dom-title-text>
76    fn Text(&self) -> DOMString {
77        self.upcast::<Node>().child_text_content()
78    }
79
80    /// <https://html.spec.whatwg.org/multipage/#dom-title-text>
81    fn SetText(&self, cx: &mut JSContext, value: DOMString) {
82        self.upcast::<Node>()
83            .set_text_content_for_element(cx, Some(value))
84    }
85}
86
87impl VirtualMethods for HTMLTitleElement {
88    fn super_type(&self) -> Option<&dyn VirtualMethods> {
89        Some(self.upcast::<HTMLElement>() as &dyn VirtualMethods)
90    }
91
92    fn children_changed(&self, cx: &mut JSContext, mutation: &ChildrenMutation) {
93        if let Some(s) = self.super_type() {
94            s.children_changed(cx, mutation);
95        }
96
97        // Notify of title changes only after the initial full parsing
98        // of the element.
99        if !self.is_currently_being_parsed.get() {
100            self.notify_title_changed();
101        }
102    }
103
104    fn bind_to_tree(&self, cx: &mut JSContext, context: &BindContext) {
105        if let Some(s) = self.super_type() {
106            s.bind_to_tree(cx, context);
107        }
108        let node = self.upcast::<Node>();
109        if context.tree_is_in_a_document_tree {
110            node.owner_doc().title_changed();
111        }
112    }
113
114    fn pop(&self, cx: &mut js::context::JSContext) {
115        if let Some(s) = self.super_type() {
116            s.pop(cx);
117        }
118
119        self.is_currently_being_parsed.set(false);
120
121        // Initial notification of title change, once the full text
122        // is available.
123        self.notify_title_changed();
124    }
125}