script/dom/html/
htmltablerowelement.rs1use dom_struct::dom_struct;
6use html5ever::{LocalName, Prefix, QualName, local_name, ns};
7use js::context::JSContext;
8use js::rust::HandleObject;
9use style::attr::{AttrValue, LengthOrPercentageOrAuto};
10use style::color::AbsoluteColor;
11
12use crate::dom::attr::Attr;
13use crate::dom::bindings::codegen::Bindings::HTMLTableElementBinding::HTMLTableElementMethods;
14use crate::dom::bindings::codegen::Bindings::HTMLTableRowElementBinding::HTMLTableRowElementMethods;
15use crate::dom::bindings::codegen::Bindings::HTMLTableSectionElementBinding::HTMLTableSectionElementMethods;
16use crate::dom::bindings::codegen::Bindings::NodeBinding::NodeMethods;
17use crate::dom::bindings::error::{ErrorResult, Fallible};
18use crate::dom::bindings::inheritance::Castable;
19use crate::dom::bindings::root::{DomRoot, LayoutDom, MutNullableDom};
20use crate::dom::bindings::str::DOMString;
21use crate::dom::document::Document;
22use crate::dom::element::{
23 CustomElementCreationMode, Element, ElementCreator, LayoutElementHelpers,
24};
25use crate::dom::html::htmlcollection::HTMLCollection;
26use crate::dom::html::htmlelement::HTMLElement;
27use crate::dom::html::htmltablecellelement::HTMLTableCellElement;
28use crate::dom::html::htmltableelement::HTMLTableElement;
29use crate::dom::html::htmltablesectionelement::HTMLTableSectionElement;
30use crate::dom::node::{Node, NodeTraits};
31use crate::dom::virtualmethods::VirtualMethods;
32use crate::script_runtime::CanGc;
33
34#[dom_struct]
35pub(crate) struct HTMLTableRowElement {
36 htmlelement: HTMLElement,
37 cells: MutNullableDom<HTMLCollection>,
38}
39
40impl HTMLTableRowElement {
41 fn new_inherited(
42 local_name: LocalName,
43 prefix: Option<Prefix>,
44 document: &Document,
45 ) -> HTMLTableRowElement {
46 HTMLTableRowElement {
47 htmlelement: HTMLElement::new_inherited(local_name, prefix, document),
48 cells: Default::default(),
49 }
50 }
51
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, cx: &mut JSContext, index: i32) -> Fallible<DomRoot<HTMLElement>> {
106 let node = self.upcast::<Node>();
107 node.insert_cell_or_row(
108 cx,
109 index,
110 || self.Cells(),
111 |cx| {
112 let cell = Element::create(
113 QualName::new(None, ns!(html), local_name!("td")),
114 None,
115 &node.owner_doc(),
116 ElementCreator::ScriptCreated,
117 CustomElementCreationMode::Asynchronous,
118 None,
119 CanGc::from_cx(cx),
120 );
121 DomRoot::downcast::<HTMLTableCellElement>(cell).unwrap()
122 },
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}