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/MappedDeclarationsBuilder.h"
12 #include "nsAttrValueInlines.h"
14 #include "mozilla/dom/HTMLTableCellElementBinding.h"
17 enum class StyleCellScope
: uint8_t { Row
, Col
, Rowgroup
, Colgroup
};
20 NS_IMPL_NS_NEW_HTML_ELEMENT(TableCell
)
22 namespace mozilla::dom
{
24 HTMLTableCellElement::~HTMLTableCellElement() = default;
26 JSObject
* HTMLTableCellElement::WrapNode(JSContext
* aCx
,
27 JS::Handle
<JSObject
*> aGivenProto
) {
28 return HTMLTableCellElement_Binding::Wrap(aCx
, this, aGivenProto
);
31 NS_IMPL_ELEMENT_CLONE(HTMLTableCellElement
)
34 HTMLTableRowElement
* HTMLTableCellElement::GetRow() const {
35 return HTMLTableRowElement::FromNodeOrNull(GetParent());
39 HTMLTableElement
* HTMLTableCellElement::GetTable() const {
40 nsIContent
* parent
= GetParent();
45 // parent should be a row.
46 nsIContent
* section
= parent
->GetParent();
51 if (section
->IsHTMLElement(nsGkAtoms::table
)) {
52 // XHTML, without a row group.
53 return static_cast<HTMLTableElement
*>(section
);
56 // We have a row group.
57 nsIContent
* result
= section
->GetParent();
58 if (result
&& result
->IsHTMLElement(nsGkAtoms::table
)) {
59 return static_cast<HTMLTableElement
*>(result
);
65 int32_t HTMLTableCellElement::CellIndex() const {
66 HTMLTableRowElement
* row
= GetRow();
71 nsIHTMLCollection
* cells
= row
->Cells();
76 uint32_t numCells
= cells
->Length();
77 for (uint32_t i
= 0; i
< numCells
; i
++) {
78 if (cells
->Item(i
) == this) {
86 StyleLockedDeclarationBlock
*
87 HTMLTableCellElement::GetMappedAttributesInheritedFromTable() const {
88 if (HTMLTableElement
* table
= GetTable()) {
89 return table
->GetAttributesMappedForCell();
94 void HTMLTableCellElement::GetAlign(DOMString
& aValue
) {
95 if (!GetAttr(nsGkAtoms::align
, aValue
)) {
96 // There's no align attribute, ask the row for the alignment.
97 HTMLTableRowElement
* row
= GetRow();
99 row
->GetAlign(aValue
);
104 static const nsAttrValue::EnumTable kCellScopeTable
[] = {
105 {"row", StyleCellScope::Row
},
106 {"col", StyleCellScope::Col
},
107 {"rowgroup", StyleCellScope::Rowgroup
},
108 {"colgroup", StyleCellScope::Colgroup
},
111 void HTMLTableCellElement::GetScope(DOMString
& aScope
) {
112 GetEnumAttr(nsGkAtoms::scope
, nullptr, aScope
);
115 bool HTMLTableCellElement::ParseAttribute(int32_t aNamespaceID
,
117 const nsAString
& aValue
,
118 nsIPrincipal
* aMaybeScriptedPrincipal
,
119 nsAttrValue
& aResult
) {
120 if (aNamespaceID
== kNameSpaceID_None
) {
121 /* ignore these attributes, stored simply as strings
122 abbr, axis, ch, headers
124 if (aAttribute
== nsGkAtoms::colspan
) {
125 aResult
.ParseClampedNonNegativeInt(aValue
, 1, 1, MAX_COLSPAN
);
128 if (aAttribute
== nsGkAtoms::rowspan
) {
129 aResult
.ParseClampedNonNegativeInt(aValue
, 1, 0, MAX_ROWSPAN
);
130 // quirks mode does not honor the special html 4 value of 0
131 if (aResult
.GetIntegerValue() == 0 && InNavQuirksMode(OwnerDoc())) {
132 aResult
.SetTo(1, &aValue
);
136 if (aAttribute
== nsGkAtoms::height
) {
137 return aResult
.ParseNonzeroHTMLDimension(aValue
);
139 if (aAttribute
== nsGkAtoms::width
) {
140 return aResult
.ParseNonzeroHTMLDimension(aValue
);
142 if (aAttribute
== nsGkAtoms::align
) {
143 return ParseTableCellHAlignValue(aValue
, aResult
);
145 if (aAttribute
== nsGkAtoms::bgcolor
) {
146 return aResult
.ParseColor(aValue
);
148 if (aAttribute
== nsGkAtoms::scope
) {
149 return aResult
.ParseEnumValue(aValue
, kCellScopeTable
, false);
151 if (aAttribute
== nsGkAtoms::valign
) {
152 return ParseTableVAlignValue(aValue
, aResult
);
156 return nsGenericHTMLElement::ParseBackgroundAttribute(
157 aNamespaceID
, aAttribute
, aValue
, aResult
) ||
158 nsGenericHTMLElement::ParseAttribute(aNamespaceID
, aAttribute
, aValue
,
159 aMaybeScriptedPrincipal
, aResult
);
162 void HTMLTableCellElement::MapAttributesIntoRule(
163 MappedDeclarationsBuilder
& aBuilder
) {
164 MapImageSizeAttributesInto(aBuilder
);
166 if (!aBuilder
.PropertyIsSet(eCSSProperty_white_space
)) {
168 if (aBuilder
.GetAttr(nsGkAtoms::nowrap
)) {
169 // See if our width is not a nonzero integer width.
170 const nsAttrValue
* value
= aBuilder
.GetAttr(nsGkAtoms::width
);
171 nsCompatibility mode
= aBuilder
.Document().GetCompatibilityMode();
172 if (!value
|| value
->Type() != nsAttrValue::eInteger
||
173 value
->GetIntegerValue() == 0 || eCompatibility_NavQuirks
!= mode
) {
174 aBuilder
.SetKeywordValue(eCSSProperty_white_space
,
175 StyleWhiteSpace::Nowrap
);
180 nsGenericHTMLElement::MapDivAlignAttributeInto(aBuilder
);
181 nsGenericHTMLElement::MapVAlignAttributeInto(aBuilder
);
182 nsGenericHTMLElement::MapBackgroundAttributesInto(aBuilder
);
183 nsGenericHTMLElement::MapCommonAttributesInto(aBuilder
);
187 HTMLTableCellElement::IsAttributeMapped(const nsAtom
* aAttribute
) const {
188 static const MappedAttributeEntry attributes
[] = {
193 // XXXldb If these are implemented, they might need to move to
194 // GetAttributeChangeHint (depending on how, and preferably not).
197 { nsGkAtoms::headers
},
198 { nsGkAtoms::scope
},
205 static const MappedAttributeEntry
* const map
[] = {
208 sBackgroundAttributeMap
,
211 return FindAttributeDependence(aAttribute
, map
);
214 nsMapRuleToAttributesFunc
HTMLTableCellElement::GetAttributeMappingFunction()
216 return &MapAttributesIntoRule
;
219 } // namespace mozilla::dom