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/. */
6
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"
14 #include "celldata.h"
15 #include "mozilla/dom/HTMLTableCellElementBinding.h"
16
17 NS_IMPL_NS_NEW_HTML_ELEMENT(TableCell)
18
19 namespace mozilla::dom {
20
21 HTMLTableCellElement::~HTMLTableCellElement() = default;
22
WrapNode(JSContext * aCx,JS::Handle<JSObject * > aGivenProto)23 JSObject* HTMLTableCellElement::WrapNode(JSContext* aCx,
24 JS::Handle<JSObject*> aGivenProto) {
25 return HTMLTableCellElement_Binding::Wrap(aCx, this, aGivenProto);
26 }
27
NS_IMPL_ELEMENT_CLONE(HTMLTableCellElement)28 NS_IMPL_ELEMENT_CLONE(HTMLTableCellElement)
29
30 // protected method
31 HTMLTableRowElement* HTMLTableCellElement::GetRow() const {
32 return HTMLTableRowElement::FromNodeOrNull(GetParent());
33 }
34
35 // protected method
GetTable() const36 HTMLTableElement* HTMLTableCellElement::GetTable() const {
37 nsIContent* parent = GetParent();
38 if (!parent) {
39 return nullptr;
40 }
41
42 // parent should be a row.
43 nsIContent* section = parent->GetParent();
44 if (!section) {
45 return nullptr;
46 }
47
48 if (section->IsHTMLElement(nsGkAtoms::table)) {
49 // XHTML, without a row group.
50 return static_cast<HTMLTableElement*>(section);
51 }
52
53 // We have a row group.
54 nsIContent* result = section->GetParent();
55 if (result && result->IsHTMLElement(nsGkAtoms::table)) {
56 return static_cast<HTMLTableElement*>(result);
57 }
58
59 return nullptr;
60 }
61
CellIndex() const62 int32_t HTMLTableCellElement::CellIndex() const {
63 HTMLTableRowElement* row = GetRow();
64 if (!row) {
65 return -1;
66 }
67
68 nsIHTMLCollection* cells = row->Cells();
69 if (!cells) {
70 return -1;
71 }
72
73 uint32_t numCells = cells->Length();
74 for (uint32_t i = 0; i < numCells; i++) {
75 if (cells->Item(i) == this) {
76 return i;
77 }
78 }
79
80 return -1;
81 }
82
83 nsMappedAttributes*
GetMappedAttributesInheritedFromTable() const84 HTMLTableCellElement::GetMappedAttributesInheritedFromTable() const {
85 if (HTMLTableElement* table = GetTable()) {
86 return table->GetAttributesMappedForCell();
87 }
88
89 return nullptr;
90 }
91
GetAlign(DOMString & aValue)92 void HTMLTableCellElement::GetAlign(DOMString& aValue) {
93 if (!GetAttr(kNameSpaceID_None, nsGkAtoms::align, aValue)) {
94 // There's no align attribute, ask the row for the alignment.
95 HTMLTableRowElement* row = GetRow();
96 if (row) {
97 row->GetAlign(aValue);
98 }
99 }
100 }
101
102 static const nsAttrValue::EnumTable kCellScopeTable[] = {
103 {"row", NS_STYLE_CELL_SCOPE_ROW},
104 {"col", NS_STYLE_CELL_SCOPE_COL},
105 {"rowgroup", NS_STYLE_CELL_SCOPE_ROWGROUP},
106 {"colgroup", NS_STYLE_CELL_SCOPE_COLGROUP},
107 {nullptr, 0}};
108
GetScope(DOMString & aScope)109 void HTMLTableCellElement::GetScope(DOMString& aScope) {
110 GetEnumAttr(nsGkAtoms::scope, nullptr, aScope);
111 }
112
ParseAttribute(int32_t aNamespaceID,nsAtom * aAttribute,const nsAString & aValue,nsIPrincipal * aMaybeScriptedPrincipal,nsAttrValue & aResult)113 bool HTMLTableCellElement::ParseAttribute(int32_t aNamespaceID,
114 nsAtom* aAttribute,
115 const nsAString& aValue,
116 nsIPrincipal* aMaybeScriptedPrincipal,
117 nsAttrValue& aResult) {
118 if (aNamespaceID == kNameSpaceID_None) {
119 /* ignore these attributes, stored simply as strings
120 abbr, axis, ch, headers
121 */
122 if (aAttribute == nsGkAtoms::colspan) {
123 aResult.ParseClampedNonNegativeInt(aValue, 1, 1, MAX_COLSPAN);
124 return true;
125 }
126 if (aAttribute == nsGkAtoms::rowspan) {
127 aResult.ParseClampedNonNegativeInt(aValue, 1, 0, MAX_ROWSPAN);
128 // quirks mode does not honor the special html 4 value of 0
129 if (aResult.GetIntegerValue() == 0 && InNavQuirksMode(OwnerDoc())) {
130 aResult.SetTo(1, &aValue);
131 }
132 return true;
133 }
134 if (aAttribute == nsGkAtoms::height) {
135 return aResult.ParseNonzeroHTMLDimension(aValue);
136 }
137 if (aAttribute == nsGkAtoms::width) {
138 return aResult.ParseNonzeroHTMLDimension(aValue);
139 }
140 if (aAttribute == nsGkAtoms::align) {
141 return ParseTableCellHAlignValue(aValue, aResult);
142 }
143 if (aAttribute == nsGkAtoms::bgcolor) {
144 return aResult.ParseColor(aValue);
145 }
146 if (aAttribute == nsGkAtoms::scope) {
147 return aResult.ParseEnumValue(aValue, kCellScopeTable, false);
148 }
149 if (aAttribute == nsGkAtoms::valign) {
150 return ParseTableVAlignValue(aValue, aResult);
151 }
152 }
153
154 return nsGenericHTMLElement::ParseBackgroundAttribute(
155 aNamespaceID, aAttribute, aValue, aResult) ||
156 nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
157 aMaybeScriptedPrincipal, aResult);
158 }
159
MapAttributesIntoRule(const nsMappedAttributes * aAttributes,MappedDeclarations & aDecls)160 void HTMLTableCellElement::MapAttributesIntoRule(
161 const nsMappedAttributes* aAttributes, MappedDeclarations& aDecls) {
162 MapImageSizeAttributesInto(aAttributes, aDecls);
163
164 if (!aDecls.PropertyIsSet(eCSSProperty_white_space)) {
165 // nowrap: enum
166 if (aAttributes->GetAttr(nsGkAtoms::nowrap)) {
167 // See if our width is not a nonzero integer width.
168 const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::width);
169 nsCompatibility mode = aDecls.Document()->GetCompatibilityMode();
170 if (!value || value->Type() != nsAttrValue::eInteger ||
171 value->GetIntegerValue() == 0 || eCompatibility_NavQuirks != mode) {
172 aDecls.SetKeywordValue(eCSSProperty_white_space,
173 StyleWhiteSpace::Nowrap);
174 }
175 }
176 }
177
178 nsGenericHTMLElement::MapDivAlignAttributeInto(aAttributes, aDecls);
179 nsGenericHTMLElement::MapVAlignAttributeInto(aAttributes, aDecls);
180 nsGenericHTMLElement::MapBackgroundAttributesInto(aAttributes, aDecls);
181 nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aDecls);
182 }
183
NS_IMETHODIMP_(bool)184 NS_IMETHODIMP_(bool)
185 HTMLTableCellElement::IsAttributeMapped(const nsAtom* aAttribute) const {
186 static const MappedAttributeEntry attributes[] = {
187 {nsGkAtoms::align},
188 {nsGkAtoms::valign},
189 {nsGkAtoms::nowrap},
190 #if 0
191 // XXXldb If these are implemented, they might need to move to
192 // GetAttributeChangeHint (depending on how, and preferably not).
193 { nsGkAtoms::abbr },
194 { nsGkAtoms::axis },
195 { nsGkAtoms::headers },
196 { nsGkAtoms::scope },
197 #endif
198 {nsGkAtoms::width},
199 {nsGkAtoms::height},
200 {nullptr}
201 };
202
203 static const MappedAttributeEntry* const map[] = {
204 attributes,
205 sCommonAttributeMap,
206 sBackgroundAttributeMap,
207 };
208
209 return FindAttributeDependence(aAttribute, map);
210 }
211
GetAttributeMappingFunction() const212 nsMapRuleToAttributesFunc HTMLTableCellElement::GetAttributeMappingFunction()
213 const {
214 return &MapAttributesIntoRule;
215 }
216
217 } // namespace mozilla::dom
218