1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "mozilla/dom/HTMLTableRowElement.h"
8 #include "mozilla/dom/HTMLTableElement.h"
9 #include "mozilla/MappedDeclarationsBuilder.h"
10 #include "nsAttrValueInlines.h"
11 #include "mozilla/dom/BindingUtils.h"
12 #include "mozilla/dom/HTMLTableRowElementBinding.h"
13 #include "nsContentList.h"
14 #include "nsContentUtils.h"
16 NS_IMPL_NS_NEW_HTML_ELEMENT(TableRow
)
18 namespace mozilla::dom
{
20 HTMLTableRowElement::~HTMLTableRowElement() = default;
22 JSObject
* HTMLTableRowElement::WrapNode(JSContext
* aCx
,
23 JS::Handle
<JSObject
*> aGivenProto
) {
24 return HTMLTableRowElement_Binding::Wrap(aCx
, this, aGivenProto
);
27 NS_IMPL_CYCLE_COLLECTION_INHERITED(HTMLTableRowElement
, nsGenericHTMLElement
,
30 NS_IMPL_ISUPPORTS_CYCLE_COLLECTION_INHERITED_0(HTMLTableRowElement
,
33 NS_IMPL_ELEMENT_CLONE(HTMLTableRowElement
)
36 HTMLTableSectionElement
* HTMLTableRowElement::GetSection() const {
37 nsIContent
* parent
= GetParent();
38 if (parent
&& parent
->IsAnyOfHTMLElements(nsGkAtoms::thead
, nsGkAtoms::tbody
,
40 return static_cast<HTMLTableSectionElement
*>(parent
);
46 HTMLTableElement
* HTMLTableRowElement::GetTable() const {
47 nsIContent
* parent
= GetParent();
52 // We may not be in a section
53 HTMLTableElement
* table
= HTMLTableElement::FromNode(parent
);
58 return HTMLTableElement::FromNodeOrNull(parent
->GetParent());
61 int32_t HTMLTableRowElement::RowIndex() const {
62 HTMLTableElement
* table
= GetTable();
67 nsIHTMLCollection
* rows
= table
->Rows();
69 uint32_t numRows
= rows
->Length();
71 for (uint32_t i
= 0; i
< numRows
; i
++) {
72 if (rows
->GetElementAt(i
) == this) {
80 int32_t HTMLTableRowElement::SectionRowIndex() const {
81 HTMLTableSectionElement
* section
= GetSection();
86 nsCOMPtr
<nsIHTMLCollection
> coll
= section
->Rows();
87 uint32_t numRows
= coll
->Length();
88 for (uint32_t i
= 0; i
< numRows
; i
++) {
89 if (coll
->GetElementAt(i
) == this) {
97 static bool IsCell(Element
* aElement
, int32_t aNamespaceID
, nsAtom
* aAtom
,
99 return aElement
->IsAnyOfHTMLElements(nsGkAtoms::td
, nsGkAtoms::th
);
102 nsIHTMLCollection
* HTMLTableRowElement::Cells() {
104 mCells
= new nsContentList(this, IsCell
,
105 nullptr, // destroy func
106 nullptr, // closure data
107 false, nullptr, kNameSpaceID_XHTML
, false);
113 already_AddRefed
<nsGenericHTMLElement
> HTMLTableRowElement::InsertCell(
114 int32_t aIndex
, ErrorResult
& aError
) {
116 aError
.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR
);
120 // Make sure mCells is initialized.
121 nsIHTMLCollection
* cells
= Cells();
123 NS_ASSERTION(mCells
, "How did that happen?");
125 nsCOMPtr
<nsINode
> nextSibling
;
126 // -1 means append, so should use null nextSibling
128 nextSibling
= cells
->Item(aIndex
);
129 // Check whether we're inserting past end of list. We want to avoid doing
130 // this unless we really have to, since this has to walk all our kids. If
131 // we have a nextSibling, we're clearly not past end of list.
133 uint32_t cellCount
= cells
->Length();
134 if (aIndex
> int32_t(cellCount
)) {
135 aError
.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR
);
142 RefPtr
<mozilla::dom::NodeInfo
> nodeInfo
;
143 nsContentUtils::QNameChanged(mNodeInfo
, nsGkAtoms::td
,
144 getter_AddRefs(nodeInfo
));
146 RefPtr
<nsGenericHTMLElement
> cell
=
147 NS_NewHTMLTableCellElement(nodeInfo
.forget());
149 aError
.Throw(NS_ERROR_OUT_OF_MEMORY
);
153 nsINode::InsertBefore(*cell
, nextSibling
, aError
);
155 return cell
.forget();
158 void HTMLTableRowElement::DeleteCell(int32_t aValue
, ErrorResult
& aError
) {
160 aError
.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR
);
164 nsIHTMLCollection
* cells
= Cells();
168 refIndex
= cells
->Length();
175 refIndex
= (uint32_t)aValue
;
178 nsCOMPtr
<nsINode
> cell
= cells
->Item(refIndex
);
180 aError
.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR
);
184 nsINode::RemoveChild(*cell
, aError
);
187 bool HTMLTableRowElement::ParseAttribute(int32_t aNamespaceID
,
189 const nsAString
& aValue
,
190 nsIPrincipal
* aMaybeScriptedPrincipal
,
191 nsAttrValue
& aResult
) {
193 * ignore these attributes, stored simply as strings
198 if (aNamespaceID
== kNameSpaceID_None
) {
199 if (aAttribute
== nsGkAtoms::height
) {
200 // Per spec should be ParseNonzeroHTMLDimension, but no browsers do that.
201 // See https://github.com/whatwg/html/issues/4716
202 return aResult
.ParseHTMLDimension(aValue
);
204 if (aAttribute
== nsGkAtoms::align
) {
205 return ParseTableCellHAlignValue(aValue
, aResult
);
207 if (aAttribute
== nsGkAtoms::bgcolor
) {
208 return aResult
.ParseColor(aValue
);
210 if (aAttribute
== nsGkAtoms::valign
) {
211 return ParseTableVAlignValue(aValue
, aResult
);
215 return nsGenericHTMLElement::ParseBackgroundAttribute(
216 aNamespaceID
, aAttribute
, aValue
, aResult
) ||
217 nsGenericHTMLElement::ParseAttribute(aNamespaceID
, aAttribute
, aValue
,
218 aMaybeScriptedPrincipal
, aResult
);
221 void HTMLTableRowElement::MapAttributesIntoRule(
222 MappedDeclarationsBuilder
& aBuilder
) {
223 nsGenericHTMLElement::MapHeightAttributeInto(aBuilder
);
224 nsGenericHTMLElement::MapDivAlignAttributeInto(aBuilder
);
225 nsGenericHTMLElement::MapVAlignAttributeInto(aBuilder
);
226 nsGenericHTMLElement::MapBackgroundAttributesInto(aBuilder
);
227 nsGenericHTMLElement::MapCommonAttributesInto(aBuilder
);
231 HTMLTableRowElement::IsAttributeMapped(const nsAtom
* aAttribute
) const {
232 static const MappedAttributeEntry attributes
[] = {
233 {nsGkAtoms::align
}, {nsGkAtoms::valign
}, {nsGkAtoms::height
}, {nullptr}};
235 static const MappedAttributeEntry
* const map
[] = {
238 sBackgroundAttributeMap
,
241 return FindAttributeDependence(aAttribute
, map
);
244 nsMapRuleToAttributesFunc
HTMLTableRowElement::GetAttributeMappingFunction()
246 return &MapAttributesIntoRule
;
249 } // namespace mozilla::dom