1use dom_struct::dom_struct;
6use js::rust::HandleObject;
7
8use crate::dom::bindings::codegen::Bindings::CharacterDataBinding::CharacterDataMethods;
9use crate::dom::bindings::codegen::Bindings::DocumentBinding::DocumentMethods;
10use crate::dom::bindings::codegen::Bindings::NodeBinding::NodeMethods;
11use crate::dom::bindings::codegen::Bindings::TextBinding::TextMethods;
12use crate::dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
13use crate::dom::bindings::error::{Error, Fallible};
14use crate::dom::bindings::inheritance::Castable;
15use crate::dom::bindings::root::{Dom, DomRoot};
16use crate::dom::bindings::str::DOMString;
17use crate::dom::characterdata::CharacterData;
18use crate::dom::document::Document;
19use crate::dom::globalscope::GlobalScope;
20use crate::dom::html::htmlslotelement::{HTMLSlotElement, Slottable};
21use crate::dom::node::Node;
22use crate::dom::window::Window;
23use crate::script_runtime::CanGc;
24
25#[dom_struct]
27pub(crate) struct Text {
28 characterdata: CharacterData,
29}
30
31impl Text {
32 pub(crate) fn new_inherited(text: DOMString, document: &Document) -> Text {
33 Text {
34 characterdata: CharacterData::new_inherited(text, document),
35 }
36 }
37
38 pub(crate) fn new(text: DOMString, document: &Document, can_gc: CanGc) -> DomRoot<Text> {
39 Self::new_with_proto(text, document, None, can_gc)
40 }
41
42 fn new_with_proto(
43 text: DOMString,
44 document: &Document,
45 proto: Option<HandleObject>,
46 can_gc: CanGc,
47 ) -> DomRoot<Text> {
48 Node::reflect_node_with_proto(
49 Box::new(Text::new_inherited(text, document)),
50 document,
51 proto,
52 can_gc,
53 )
54 }
55}
56
57impl TextMethods<crate::DomTypeHolder> for Text {
58 fn Constructor(
60 window: &Window,
61 proto: Option<HandleObject>,
62 can_gc: CanGc,
63 text: DOMString,
64 ) -> Fallible<DomRoot<Text>> {
65 let document = window.Document();
66 Ok(Text::new_with_proto(text, &document, proto, can_gc))
67 }
68
69 fn SplitText(&self, offset: u32, can_gc: CanGc) -> Fallible<DomRoot<Text>> {
72 let cdata = self.upcast::<CharacterData>();
73 let length = cdata.Length();
75 if offset > length {
76 return Err(Error::IndexSize);
78 }
79 let count = length - offset;
81 let new_data = cdata.SubstringData(offset, count).unwrap();
83 let node = self.upcast::<Node>();
85 let owner_doc = node.owner_doc();
86 let new_node = owner_doc.CreateTextNode(new_data, can_gc);
87 let parent = node.GetParentNode();
89 if let Some(ref parent) = parent {
90 parent
92 .InsertBefore(new_node.upcast(), node.GetNextSibling().as_deref(), can_gc)
93 .unwrap();
94 node.ranges()
96 .move_to_following_text_sibling_above(node, offset, new_node.upcast());
97 parent.ranges().increment_at(parent, node.index() + 1);
99 }
100 cdata.DeleteData(offset, count).unwrap();
102 Ok(new_node)
104 }
105
106 fn WholeText(&self) -> DOMString {
108 let first = self
109 .upcast::<Node>()
110 .inclusively_preceding_siblings()
111 .take_while(|node| node.is::<Text>())
112 .last()
113 .unwrap();
114 let nodes = first
115 .inclusively_following_siblings()
116 .take_while(|node| node.is::<Text>());
117 let mut text = String::new();
118 for ref node in nodes {
119 let cdata = node.downcast::<CharacterData>().unwrap();
120 text.push_str(&cdata.data());
121 }
122 DOMString::from(text)
123 }
124
125 fn GetAssignedSlot(&self) -> Option<DomRoot<HTMLSlotElement>> {
127 let cx = GlobalScope::get_cx();
128
129 rooted!(in(*cx) let slottable = Slottable(Dom::from_ref(self.upcast::<Node>())));
132 slottable.find_a_slot(true)
133 }
134}