script/dom/html/
htmltablerowelement.rs1use dom_struct::dom_struct;
6use html5ever::{LocalName, Prefix, QualName, local_name, ns};
7use js::rust::HandleObject;
8use style::attr::{AttrValue, LengthOrPercentageOrAuto};
9use style::color::AbsoluteColor;
10
11use crate::dom::attr::Attr;
12use crate::dom::bindings::codegen::Bindings::HTMLTableElementBinding::HTMLTableElementMethods;
13use crate::dom::bindings::codegen::Bindings::HTMLTableRowElementBinding::HTMLTableRowElementMethods;
14use crate::dom::bindings::codegen::Bindings::HTMLTableSectionElementBinding::HTMLTableSectionElementMethods;
15use crate::dom::bindings::codegen::Bindings::NodeBinding::NodeMethods;
16use crate::dom::bindings::error::{ErrorResult, Fallible};
17use crate::dom::bindings::inheritance::Castable;
18use crate::dom::bindings::root::{DomRoot, LayoutDom, MutNullableDom};
19use crate::dom::bindings::str::DOMString;
20use crate::dom::document::Document;
21use crate::dom::element::{
22 CustomElementCreationMode, Element, ElementCreator, LayoutElementHelpers,
23};
24use crate::dom::html::htmlcollection::HTMLCollection;
25use crate::dom::html::htmlelement::HTMLElement;
26use crate::dom::html::htmltablecellelement::HTMLTableCellElement;
27use crate::dom::html::htmltableelement::HTMLTableElement;
28use crate::dom::html::htmltablesectionelement::HTMLTableSectionElement;
29use crate::dom::node::{Node, NodeTraits};
30use crate::dom::virtualmethods::VirtualMethods;
31use crate::script_runtime::CanGc;
32
33#[dom_struct]
34pub(crate) struct HTMLTableRowElement {
35 htmlelement: HTMLElement,
36 cells: MutNullableDom<HTMLCollection>,
37}
38
39impl HTMLTableRowElement {
40 fn new_inherited(
41 local_name: LocalName,
42 prefix: Option<Prefix>,
43 document: &Document,
44 ) -> HTMLTableRowElement {
45 HTMLTableRowElement {
46 htmlelement: HTMLElement::new_inherited(local_name, prefix, document),
47 cells: Default::default(),
48 }
49 }
50
51 #[cfg_attr(crown, allow(crown::unrooted_must_root))]
52 pub(crate) fn new(
53 local_name: LocalName,
54 prefix: Option<Prefix>,
55 document: &Document,
56 proto: Option<HandleObject>,
57 can_gc: CanGc,
58 ) -> DomRoot<HTMLTableRowElement> {
59 let n = Node::reflect_node_with_proto(
60 Box::new(HTMLTableRowElement::new_inherited(
61 local_name, prefix, document,
62 )),
63 document,
64 proto,
65 can_gc,
66 );
67
68 n.upcast::<Node>().set_weird_parser_insertion_mode();
69 n
70 }
71
72 fn row_index(&self, collection: DomRoot<HTMLCollection>) -> i32 {
75 collection
76 .elements_iter()
77 .position(|elem| (&elem as &Element) == self.upcast())
78 .map_or(-1, |i| i as i32)
79 }
80}
81
82impl HTMLTableRowElementMethods<crate::DomTypeHolder> for HTMLTableRowElement {
83 make_getter!(BgColor, "bgcolor");
85
86 make_legacy_color_setter!(SetBgColor, "bgcolor");
88
89 fn Cells(&self) -> DomRoot<HTMLCollection> {
91 self.cells.or_init(|| {
92 HTMLCollection::new_with_filter_fn(
93 &self.owner_window(),
94 self.upcast(),
95 |element, root| {
96 (element.is::<HTMLTableCellElement>()) &&
97 element.upcast::<Node>().GetParentNode().as_deref() == Some(root)
98 },
99 CanGc::note(),
100 )
101 })
102 }
103
104 fn InsertCell(&self, index: i32, can_gc: CanGc) -> Fallible<DomRoot<HTMLElement>> {
106 let node = self.upcast::<Node>();
107 node.insert_cell_or_row(
108 index,
109 || self.Cells(),
110 || {
111 let cell = Element::create(
112 QualName::new(None, ns!(html), local_name!("td")),
113 None,
114 &node.owner_doc(),
115 ElementCreator::ScriptCreated,
116 CustomElementCreationMode::Asynchronous,
117 None,
118 can_gc,
119 );
120 DomRoot::downcast::<HTMLTableCellElement>(cell).unwrap()
121 },
122 can_gc,
123 )
124 }
125
126 fn DeleteCell(&self, index: i32) -> ErrorResult {
128 let node = self.upcast::<Node>();
129 node.delete_cell_or_row(
130 index,
131 || self.Cells(),
132 |n| n.is::<HTMLTableCellElement>(),
133 CanGc::note(),
134 )
135 }
136
137 fn RowIndex(&self) -> i32 {
139 let parent = match self.upcast::<Node>().GetParentNode() {
140 Some(parent) => parent,
141 None => return -1,
142 };
143 if let Some(table) = parent.downcast::<HTMLTableElement>() {
144 return self.row_index(table.Rows());
145 }
146 if !parent.is::<HTMLTableSectionElement>() {
147 return -1;
148 }
149 let grandparent = match parent.upcast::<Node>().GetParentNode() {
150 Some(parent) => parent,
151 None => return -1,
152 };
153 grandparent
154 .downcast::<HTMLTableElement>()
155 .map_or(-1, |table| self.row_index(table.Rows()))
156 }
157
158 fn SectionRowIndex(&self) -> i32 {
160 let parent = match self.upcast::<Node>().GetParentNode() {
161 Some(parent) => parent,
162 None => return -1,
163 };
164 let collection = if let Some(table) = parent.downcast::<HTMLTableElement>() {
165 table.Rows()
166 } else if let Some(table_section) = parent.downcast::<HTMLTableSectionElement>() {
167 table_section.Rows()
168 } else {
169 return -1;
170 };
171 self.row_index(collection)
172 }
173}
174
175pub(crate) trait HTMLTableRowElementLayoutHelpers {
176 fn get_background_color(self) -> Option<AbsoluteColor>;
177 fn get_height(self) -> LengthOrPercentageOrAuto;
178}
179
180impl HTMLTableRowElementLayoutHelpers for LayoutDom<'_, HTMLTableRowElement> {
181 fn get_background_color(self) -> Option<AbsoluteColor> {
182 self.upcast::<Element>()
183 .get_attr_for_layout(&ns!(), &local_name!("bgcolor"))
184 .and_then(AttrValue::as_color)
185 .cloned()
186 }
187
188 fn get_height(self) -> LengthOrPercentageOrAuto {
189 self.upcast::<Element>()
190 .get_attr_for_layout(&ns!(), &local_name!("height"))
191 .map(AttrValue::as_dimension)
192 .cloned()
193 .unwrap_or(LengthOrPercentageOrAuto::Auto)
194 }
195}
196
197impl VirtualMethods for HTMLTableRowElement {
198 fn super_type(&self) -> Option<&dyn VirtualMethods> {
199 Some(self.upcast::<HTMLElement>() as &dyn VirtualMethods)
200 }
201
202 fn attribute_affects_presentational_hints(&self, attr: &Attr) -> bool {
203 match attr.local_name() {
204 &local_name!("height") => true,
205 _ => self
206 .super_type()
207 .unwrap()
208 .attribute_affects_presentational_hints(attr),
209 }
210 }
211
212 fn parse_plain_attribute(&self, local_name: &LocalName, value: DOMString) -> AttrValue {
213 match *local_name {
214 local_name!("bgcolor") => AttrValue::from_legacy_color(value.into()),
215 local_name!("height") => AttrValue::from_dimension(value.into()),
216 _ => self
217 .super_type()
218 .unwrap()
219 .parse_plain_attribute(local_name, value),
220 }
221 }
222}