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/HTMLTableCellElement.h"
8 #include "mozilla/dom/Document.h"
9 #include "mozilla/dom/HTMLTableElement.h"
10 #include "mozilla/dom/HTMLTableRowElement.h"
11 #include "mozilla/MappedDeclarations.h"
12 #include "nsMappedAttributes.h"
13 #include "nsAttrValueInlines.h"
15 #include "mozilla/dom/HTMLTableCellElementBinding.h"
18 enum class StyleCellScope
: uint8_t { Row
, Col
, Rowgroup
, Colgroup
};
21 NS_IMPL_NS_NEW_HTML_ELEMENT(TableCell
)
23 namespace mozilla::dom
{
25 HTMLTableCellElement::~HTMLTableCellElement() = default;
27 JSObject
* HTMLTableCellElement::WrapNode(JSContext
* aCx
,
28 JS::Handle
<JSObject
*> aGivenProto
) {
29 return HTMLTableCellElement_Binding::Wrap(aCx
, this, aGivenProto
);
32 NS_IMPL_ELEMENT_CLONE(HTMLTableCellElement
)
35 HTMLTableRowElement
* HTMLTableCellElement::GetRow() const {
36 return HTMLTableRowElement::FromNodeOrNull(GetParent());
40 HTMLTableElement
* HTMLTableCellElement::GetTable() const {
41 nsIContent
* parent
= GetParent();
46 // parent should be a row.
47 nsIContent
* section
= parent
->GetParent();
52 if (section
->IsHTMLElement(nsGkAtoms::table
)) {
53 // XHTML, without a row group.
54 return static_cast<HTMLTableElement
*>(section
);
57 // We have a row group.
58 nsIContent
* result
= section
->GetParent();
59 if (result
&& result
->IsHTMLElement(nsGkAtoms::table
)) {
60 return static_cast<HTMLTableElement
*>(result
);
66 int32_t HTMLTableCellElement::CellIndex() const {
67 HTMLTableRowElement
* row
= GetRow();
72 nsIHTMLCollection
* cells
= row
->Cells();
77 uint32_t numCells
= cells
->Length();
78 for (uint32_t i
= 0; i
< numCells
; i
++) {
79 if (cells
->Item(i
) == this) {
88 HTMLTableCellElement::GetMappedAttributesInheritedFromTable() const {
89 if (HTMLTableElement
* table
= GetTable()) {
90 return table
->GetAttributesMappedForCell();
96 void HTMLTableCellElement::GetAlign(DOMString
& aValue
) {
97 if (!GetAttr(kNameSpaceID_None
, nsGkAtoms::align
, aValue
)) {
98 // There's no align attribute, ask the row for the alignment.
99 HTMLTableRowElement
* row
= GetRow();
101 row
->GetAlign(aValue
);
106 static const nsAttrValue::EnumTable kCellScopeTable
[] = {
107 {"row", StyleCellScope::Row
},
108 {"col", StyleCellScope::Col
},
109 {"rowgroup", StyleCellScope::Rowgroup
},
110 {"colgroup", StyleCellScope::Colgroup
},
113 void HTMLTableCellElement::GetScope(DOMString
& aScope
) {
114 GetEnumAttr(nsGkAtoms::scope
, nullptr, aScope
);
117 bool HTMLTableCellElement::ParseAttribute(int32_t aNamespaceID
,
119 const nsAString
& aValue
,
120 nsIPrincipal
* aMaybeScriptedPrincipal
,
121 nsAttrValue
& aResult
) {
122 if (aNamespaceID
== kNameSpaceID_None
) {
123 /* ignore these attributes, stored simply as strings
124 abbr, axis, ch, headers
126 if (aAttribute
== nsGkAtoms::colspan
) {
127 aResult
.ParseClampedNonNegativeInt(aValue
, 1, 1, MAX_COLSPAN
);
130 if (aAttribute
== nsGkAtoms::rowspan
) {
131 aResult
.ParseClampedNonNegativeInt(aValue
, 1, 0, MAX_ROWSPAN
);
132 // quirks mode does not honor the special html 4 value of 0
133 if (aResult
.GetIntegerValue() == 0 && InNavQuirksMode(OwnerDoc())) {
134 aResult
.SetTo(1, &aValue
);
138 if (aAttribute
== nsGkAtoms::height
) {
139 return aResult
.ParseNonzeroHTMLDimension(aValue
);
141 if (aAttribute
== nsGkAtoms::width
) {
142 return aResult
.ParseNonzeroHTMLDimension(aValue
);
144 if (aAttribute
== nsGkAtoms::align
) {
145 return ParseTableCellHAlignValue(aValue
, aResult
);
147 if (aAttribute
== nsGkAtoms::bgcolor
) {
148 return aResult
.ParseColor(aValue
);
150 if (aAttribute
== nsGkAtoms::scope
) {
151 return aResult
.ParseEnumValue(aValue
, kCellScopeTable
, false);
153 if (aAttribute
== nsGkAtoms::valign
) {
154 return ParseTableVAlignValue(aValue
, aResult
);
158 return nsGenericHTMLElement::ParseBackgroundAttribute(
159 aNamespaceID
, aAttribute
, aValue
, aResult
) ||
160 nsGenericHTMLElement::ParseAttribute(aNamespaceID
, aAttribute
, aValue
,
161 aMaybeScriptedPrincipal
, aResult
);
164 void HTMLTableCellElement::MapAttributesIntoRule(
165 const nsMappedAttributes
* aAttributes
, MappedDeclarations
& aDecls
) {
166 MapImageSizeAttributesInto(aAttributes
, aDecls
);
168 if (!aDecls
.PropertyIsSet(eCSSProperty_white_space
)) {
170 if (aAttributes
->GetAttr(nsGkAtoms::nowrap
)) {
171 // See if our width is not a nonzero integer width.
172 const nsAttrValue
* value
= aAttributes
->GetAttr(nsGkAtoms::width
);
173 nsCompatibility mode
= aDecls
.Document()->GetCompatibilityMode();
174 if (!value
|| value
->Type() != nsAttrValue::eInteger
||
175 value
->GetIntegerValue() == 0 || eCompatibility_NavQuirks
!= mode
) {
176 aDecls
.SetKeywordValue(eCSSProperty_white_space
,
177 StyleWhiteSpace::Nowrap
);
182 nsGenericHTMLElement::MapDivAlignAttributeInto(aAttributes
, aDecls
);
183 nsGenericHTMLElement::MapVAlignAttributeInto(aAttributes
, aDecls
);
184 nsGenericHTMLElement::MapBackgroundAttributesInto(aAttributes
, aDecls
);
185 nsGenericHTMLElement::MapCommonAttributesInto(aAttributes
, aDecls
);
189 HTMLTableCellElement::IsAttributeMapped(const nsAtom
* aAttribute
) const {
190 static const MappedAttributeEntry attributes
[] = {
195 // XXXldb If these are implemented, they might need to move to
196 // GetAttributeChangeHint (depending on how, and preferably not).
199 { nsGkAtoms::headers
},
200 { nsGkAtoms::scope
},
207 static const MappedAttributeEntry
* const map
[] = {
210 sBackgroundAttributeMap
,
213 return FindAttributeDependence(aAttribute
, map
);
216 nsMapRuleToAttributesFunc
HTMLTableCellElement::GetAttributeMappingFunction()
218 return &MapAttributesIntoRule
;
221 } // namespace mozilla::dom