Line data Source code
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/HTMLTableElement.h"
9 : #include "mozilla/dom/HTMLTableRowElement.h"
10 : #include "mozilla/GenericSpecifiedValuesInlines.h"
11 : #include "nsMappedAttributes.h"
12 : #include "nsAttrValueInlines.h"
13 : #include "nsRuleWalker.h"
14 : #include "celldata.h"
15 : #include "mozilla/dom/HTMLTableCellElementBinding.h"
16 :
17 0 : NS_IMPL_NS_NEW_HTML_ELEMENT(TableCell)
18 :
19 : namespace mozilla {
20 : namespace dom {
21 :
22 0 : HTMLTableCellElement::~HTMLTableCellElement()
23 : {
24 0 : }
25 :
26 : JSObject*
27 0 : HTMLTableCellElement::WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto)
28 : {
29 0 : return HTMLTableCellElementBinding::Wrap(aCx, this, aGivenProto);
30 : }
31 :
32 0 : NS_IMPL_ISUPPORTS_INHERITED(HTMLTableCellElement, nsGenericHTMLElement,
33 : nsIDOMHTMLTableCellElement)
34 :
35 0 : NS_IMPL_ELEMENT_CLONE(HTMLTableCellElement)
36 :
37 :
38 : // protected method
39 : HTMLTableRowElement*
40 0 : HTMLTableCellElement::GetRow() const
41 : {
42 0 : return HTMLTableRowElement::FromContentOrNull(GetParent());
43 : }
44 :
45 : // protected method
46 : HTMLTableElement*
47 0 : HTMLTableCellElement::GetTable() const
48 : {
49 0 : nsIContent *parent = GetParent();
50 0 : if (!parent) {
51 0 : return nullptr;
52 : }
53 :
54 : // parent should be a row.
55 0 : nsIContent* section = parent->GetParent();
56 0 : if (!section) {
57 0 : return nullptr;
58 : }
59 :
60 0 : if (section->IsHTMLElement(nsGkAtoms::table)) {
61 : // XHTML, without a row group.
62 0 : return static_cast<HTMLTableElement*>(section);
63 : }
64 :
65 : // We have a row group.
66 0 : nsIContent* result = section->GetParent();
67 0 : if (result && result->IsHTMLElement(nsGkAtoms::table)) {
68 0 : return static_cast<HTMLTableElement*>(result);
69 : }
70 :
71 0 : return nullptr;
72 : }
73 :
74 : int32_t
75 0 : HTMLTableCellElement::CellIndex() const
76 : {
77 0 : HTMLTableRowElement* row = GetRow();
78 0 : if (!row) {
79 0 : return -1;
80 : }
81 :
82 0 : nsIHTMLCollection* cells = row->Cells();
83 0 : if (!cells) {
84 0 : return -1;
85 : }
86 :
87 0 : uint32_t numCells = cells->Length();
88 0 : for (uint32_t i = 0; i < numCells; i++) {
89 0 : if (cells->Item(i) == this) {
90 0 : return i;
91 : }
92 : }
93 :
94 0 : return -1;
95 : }
96 :
97 : NS_IMETHODIMP
98 0 : HTMLTableCellElement::GetCellIndex(int32_t* aCellIndex)
99 : {
100 0 : *aCellIndex = CellIndex();
101 0 : return NS_OK;
102 : }
103 :
104 : NS_IMETHODIMP
105 0 : HTMLTableCellElement::WalkContentStyleRules(nsRuleWalker* aRuleWalker)
106 : {
107 0 : nsresult rv = nsGenericHTMLElement::WalkContentStyleRules(aRuleWalker);
108 0 : NS_ENSURE_SUCCESS(rv, rv);
109 :
110 0 : if (nsMappedAttributes* tableInheritedAttributes = GetMappedAttributesInheritedFromTable()) {
111 0 : if (tableInheritedAttributes) {
112 0 : aRuleWalker->Forward(tableInheritedAttributes);
113 : }
114 : }
115 0 : return NS_OK;
116 : }
117 :
118 : nsMappedAttributes*
119 0 : HTMLTableCellElement::GetMappedAttributesInheritedFromTable() const
120 : {
121 0 : if (HTMLTableElement* table = GetTable()) {
122 0 : return table->GetAttributesMappedForCell();
123 : }
124 :
125 0 : return nullptr;
126 : }
127 :
128 : NS_IMETHODIMP
129 0 : HTMLTableCellElement::SetAbbr(const nsAString& aAbbr)
130 : {
131 0 : ErrorResult rv;
132 0 : SetAbbr(aAbbr, rv);
133 0 : return rv.StealNSResult();
134 : }
135 :
136 : NS_IMETHODIMP
137 0 : HTMLTableCellElement::GetAbbr(nsAString& aAbbr)
138 : {
139 0 : DOMString abbr;
140 0 : GetAbbr(abbr);
141 0 : abbr.ToString(aAbbr);
142 0 : return NS_OK;
143 : }
144 :
145 : NS_IMETHODIMP
146 0 : HTMLTableCellElement::SetAxis(const nsAString& aAxis)
147 : {
148 0 : ErrorResult rv;
149 0 : SetAxis(aAxis, rv);
150 0 : return rv.StealNSResult();
151 : }
152 :
153 : NS_IMETHODIMP
154 0 : HTMLTableCellElement::GetAxis(nsAString& aAxis)
155 : {
156 0 : DOMString axis;
157 0 : GetAxis(axis);
158 0 : axis.ToString(aAxis);
159 0 : return NS_OK;
160 : }
161 :
162 : NS_IMETHODIMP
163 0 : HTMLTableCellElement::SetAlign(const nsAString& aAlign)
164 : {
165 0 : ErrorResult rv;
166 0 : SetAlign(aAlign, rv);
167 0 : return rv.StealNSResult();
168 : }
169 :
170 : NS_IMETHODIMP
171 0 : HTMLTableCellElement::GetAlign(nsAString& aAlign)
172 : {
173 0 : DOMString align;
174 0 : GetAlign(align);
175 0 : align.ToString(aAlign);
176 0 : return NS_OK;
177 : }
178 :
179 : NS_IMETHODIMP
180 0 : HTMLTableCellElement::SetVAlign(const nsAString& aVAlign)
181 : {
182 0 : ErrorResult rv;
183 0 : SetVAlign(aVAlign, rv);
184 0 : return rv.StealNSResult();
185 : }
186 :
187 : NS_IMETHODIMP
188 0 : HTMLTableCellElement::GetVAlign(nsAString& aVAlign)
189 : {
190 0 : DOMString vAlign;
191 0 : GetVAlign(vAlign);
192 0 : vAlign.ToString(aVAlign);
193 0 : return NS_OK;
194 : }
195 :
196 : NS_IMETHODIMP
197 0 : HTMLTableCellElement::SetCh(const nsAString& aCh)
198 : {
199 0 : ErrorResult rv;
200 0 : SetCh(aCh, rv);
201 0 : return rv.StealNSResult();
202 : }
203 :
204 : NS_IMETHODIMP
205 0 : HTMLTableCellElement::GetCh(nsAString& aCh)
206 : {
207 0 : DOMString ch;
208 0 : GetCh(ch);
209 0 : ch.ToString(aCh);
210 0 : return NS_OK;
211 : }
212 :
213 : NS_IMETHODIMP
214 0 : HTMLTableCellElement::SetChOff(const nsAString& aChOff)
215 : {
216 0 : ErrorResult rv;
217 0 : SetChOff(aChOff, rv);
218 0 : return rv.StealNSResult();
219 : }
220 :
221 : NS_IMETHODIMP
222 0 : HTMLTableCellElement::GetChOff(nsAString& aChOff)
223 : {
224 0 : DOMString chOff;
225 0 : GetChOff(chOff);
226 0 : chOff.ToString(aChOff);
227 0 : return NS_OK;
228 : }
229 :
230 : NS_IMETHODIMP
231 0 : HTMLTableCellElement::SetBgColor(const nsAString& aBgColor)
232 : {
233 0 : ErrorResult rv;
234 0 : SetBgColor(aBgColor, rv);
235 0 : return rv.StealNSResult();
236 : }
237 :
238 : NS_IMETHODIMP
239 0 : HTMLTableCellElement::GetBgColor(nsAString& aBgColor)
240 : {
241 0 : DOMString bgColor;
242 0 : GetBgColor(bgColor);
243 0 : bgColor.ToString(aBgColor);
244 0 : return NS_OK;
245 : }
246 :
247 : NS_IMETHODIMP
248 0 : HTMLTableCellElement::SetHeight(const nsAString& aHeight)
249 : {
250 0 : ErrorResult rv;
251 0 : SetHeight(aHeight, rv);
252 0 : return rv.StealNSResult();
253 : }
254 :
255 : NS_IMETHODIMP
256 0 : HTMLTableCellElement::GetHeight(nsAString& aHeight)
257 : {
258 0 : DOMString height;
259 0 : GetHeight(height);
260 0 : height.ToString(aHeight);
261 0 : return NS_OK;
262 : }
263 :
264 : NS_IMETHODIMP
265 0 : HTMLTableCellElement::SetWidth(const nsAString& aWidth)
266 : {
267 0 : ErrorResult rv;
268 0 : SetWidth(aWidth, rv);
269 0 : return rv.StealNSResult();
270 : }
271 :
272 : NS_IMETHODIMP
273 0 : HTMLTableCellElement::GetWidth(nsAString& aWidth)
274 : {
275 0 : DOMString width;
276 0 : GetWidth(width);
277 0 : width.ToString(aWidth);
278 0 : return NS_OK;
279 : }
280 :
281 : NS_IMETHODIMP
282 0 : HTMLTableCellElement::SetNoWrap(bool aNoWrap)
283 : {
284 0 : ErrorResult rv;
285 0 : SetNoWrap(aNoWrap, rv);
286 0 : return rv.StealNSResult();
287 : }
288 :
289 : NS_IMETHODIMP
290 0 : HTMLTableCellElement::GetNoWrap(bool* aNoWrap)
291 : {
292 0 : *aNoWrap = NoWrap();
293 0 : return NS_OK;
294 : }
295 :
296 : NS_IMETHODIMP
297 0 : HTMLTableCellElement::SetScope(const nsAString& aScope)
298 : {
299 0 : ErrorResult rv;
300 0 : SetScope(aScope, rv);
301 0 : return rv.StealNSResult();
302 : }
303 :
304 : NS_IMETHODIMP
305 0 : HTMLTableCellElement::GetScope(nsAString& aScope)
306 : {
307 0 : DOMString scope;
308 0 : GetScope(scope);
309 0 : scope.ToString(aScope);
310 0 : return NS_OK;
311 : }
312 :
313 : NS_IMETHODIMP
314 0 : HTMLTableCellElement::SetHeaders(const nsAString& aHeaders)
315 : {
316 0 : ErrorResult rv;
317 0 : SetHeaders(aHeaders, rv);
318 0 : return rv.StealNSResult();
319 : }
320 :
321 : NS_IMETHODIMP
322 0 : HTMLTableCellElement::GetHeaders(nsAString& aHeaders)
323 : {
324 0 : DOMString headers;
325 0 : GetHeaders(headers);
326 0 : headers.ToString(aHeaders);
327 0 : return NS_OK;
328 : }
329 :
330 : NS_IMETHODIMP
331 0 : HTMLTableCellElement::SetColSpan(int32_t aColSpan)
332 : {
333 0 : ErrorResult rv;
334 0 : SetColSpan(aColSpan, rv);
335 0 : return rv.StealNSResult();
336 : }
337 :
338 : NS_IMETHODIMP
339 0 : HTMLTableCellElement::GetColSpan(int32_t* aColSpan)
340 : {
341 0 : *aColSpan = ColSpan();
342 0 : return NS_OK;
343 : }
344 :
345 : NS_IMETHODIMP
346 0 : HTMLTableCellElement::SetRowSpan(int32_t aRowSpan)
347 : {
348 0 : ErrorResult rv;
349 0 : SetRowSpan(aRowSpan, rv);
350 0 : return rv.StealNSResult();
351 : }
352 :
353 : NS_IMETHODIMP
354 0 : HTMLTableCellElement::GetRowSpan(int32_t* aRowSpan)
355 : {
356 0 : *aRowSpan = RowSpan();
357 0 : return NS_OK;
358 : }
359 :
360 : void
361 0 : HTMLTableCellElement::GetAlign(DOMString& aValue)
362 : {
363 0 : if (!GetAttr(kNameSpaceID_None, nsGkAtoms::align, aValue)) {
364 : // There's no align attribute, ask the row for the alignment.
365 0 : HTMLTableRowElement* row = GetRow();
366 0 : if (row) {
367 0 : row->GetAlign(aValue);
368 : }
369 : }
370 0 : }
371 :
372 : static const nsAttrValue::EnumTable kCellScopeTable[] = {
373 : { "row", NS_STYLE_CELL_SCOPE_ROW },
374 : { "col", NS_STYLE_CELL_SCOPE_COL },
375 : { "rowgroup", NS_STYLE_CELL_SCOPE_ROWGROUP },
376 : { "colgroup", NS_STYLE_CELL_SCOPE_COLGROUP },
377 : { nullptr, 0 }
378 : };
379 :
380 : void
381 0 : HTMLTableCellElement::GetScope(DOMString& aScope)
382 : {
383 0 : GetEnumAttr(nsGkAtoms::scope, nullptr, aScope);
384 0 : }
385 :
386 : bool
387 0 : HTMLTableCellElement::ParseAttribute(int32_t aNamespaceID,
388 : nsIAtom* aAttribute,
389 : const nsAString& aValue,
390 : nsAttrValue& aResult)
391 : {
392 0 : if (aNamespaceID == kNameSpaceID_None) {
393 : /* ignore these attributes, stored simply as strings
394 : abbr, axis, ch, headers
395 : */
396 0 : if (aAttribute == nsGkAtoms::charoff) {
397 : /* attributes that resolve to integers with a min of 0 */
398 0 : return aResult.ParseIntWithBounds(aValue, 0);
399 : }
400 0 : if (aAttribute == nsGkAtoms::colspan) {
401 0 : aResult.ParseClampedNonNegativeInt(aValue, 1, 1, MAX_COLSPAN);
402 0 : return true;
403 : }
404 0 : if (aAttribute == nsGkAtoms::rowspan) {
405 0 : aResult.ParseClampedNonNegativeInt(aValue, 1, 0, MAX_ROWSPAN);
406 : // quirks mode does not honor the special html 4 value of 0
407 0 : if (aResult.GetIntegerValue() == 0 && InNavQuirksMode(OwnerDoc())) {
408 0 : aResult.SetTo(1, &aValue);
409 : }
410 0 : return true;
411 : }
412 0 : if (aAttribute == nsGkAtoms::height) {
413 0 : return aResult.ParseSpecialIntValue(aValue);
414 : }
415 0 : if (aAttribute == nsGkAtoms::width) {
416 0 : return aResult.ParseSpecialIntValue(aValue);
417 : }
418 0 : if (aAttribute == nsGkAtoms::align) {
419 0 : return ParseTableCellHAlignValue(aValue, aResult);
420 : }
421 0 : if (aAttribute == nsGkAtoms::bgcolor) {
422 0 : return aResult.ParseColor(aValue);
423 : }
424 0 : if (aAttribute == nsGkAtoms::scope) {
425 0 : return aResult.ParseEnumValue(aValue, kCellScopeTable, false);
426 : }
427 0 : if (aAttribute == nsGkAtoms::valign) {
428 0 : return ParseTableVAlignValue(aValue, aResult);
429 : }
430 : }
431 :
432 0 : return nsGenericHTMLElement::ParseBackgroundAttribute(aNamespaceID,
433 : aAttribute, aValue,
434 0 : aResult) ||
435 0 : nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
436 0 : aResult);
437 : }
438 :
439 : void
440 0 : HTMLTableCellElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
441 : GenericSpecifiedValues* aData)
442 : {
443 0 : if (aData->ShouldComputeStyleStruct(NS_STYLE_INHERIT_BIT(Position))) {
444 : // width: value
445 0 : if (!aData->PropertyIsSet(eCSSProperty_width)) {
446 0 : const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::width);
447 0 : if (value && value->Type() == nsAttrValue::eInteger) {
448 0 : if (value->GetIntegerValue() > 0)
449 0 : aData->SetPixelValue(eCSSProperty_width, (float)value->GetIntegerValue());
450 : // else 0 implies auto for compatibility.
451 : }
452 0 : else if (value && value->Type() == nsAttrValue::ePercent) {
453 0 : if (value->GetPercentValue() > 0.0f)
454 0 : aData->SetPercentValue(eCSSProperty_width, value->GetPercentValue());
455 : // else 0 implies auto for compatibility
456 : }
457 : }
458 : // height: value
459 0 : if (!aData->PropertyIsSet(eCSSProperty_height)) {
460 0 : const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::height);
461 0 : if (value && value->Type() == nsAttrValue::eInteger) {
462 0 : if (value->GetIntegerValue() > 0)
463 0 : aData->SetPixelValue(eCSSProperty_height, (float)value->GetIntegerValue());
464 : // else 0 implies auto for compatibility.
465 : }
466 0 : else if (value && value->Type() == nsAttrValue::ePercent) {
467 0 : if (value->GetPercentValue() > 0.0f)
468 0 : aData->SetPercentValue(eCSSProperty_height, value->GetPercentValue());
469 : // else 0 implies auto for compatibility
470 : }
471 : }
472 : }
473 0 : if (aData->ShouldComputeStyleStruct(NS_STYLE_INHERIT_BIT(Text))) {
474 0 : if (!aData->PropertyIsSet(eCSSProperty_white_space)) {
475 : // nowrap: enum
476 0 : if (aAttributes->GetAttr(nsGkAtoms::nowrap)) {
477 : // See if our width is not a nonzero integer width.
478 0 : const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::width);
479 0 : nsCompatibility mode = aData->PresContext()->CompatibilityMode();
480 0 : if (!value || value->Type() != nsAttrValue::eInteger ||
481 0 : value->GetIntegerValue() == 0 ||
482 : eCompatibility_NavQuirks != mode) {
483 0 : aData->SetKeywordValue(eCSSProperty_white_space, StyleWhiteSpace::Nowrap);
484 : }
485 : }
486 : }
487 : }
488 :
489 0 : nsGenericHTMLElement::MapDivAlignAttributeInto(aAttributes, aData);
490 0 : nsGenericHTMLElement::MapVAlignAttributeInto(aAttributes, aData);
491 0 : nsGenericHTMLElement::MapBackgroundAttributesInto(aAttributes, aData);
492 0 : nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aData);
493 0 : }
494 :
495 : NS_IMETHODIMP_(bool)
496 0 : HTMLTableCellElement::IsAttributeMapped(const nsIAtom* aAttribute) const
497 : {
498 : static const MappedAttributeEntry attributes[] = {
499 : { &nsGkAtoms::align },
500 : { &nsGkAtoms::valign },
501 : { &nsGkAtoms::nowrap },
502 : #if 0
503 : // XXXldb If these are implemented, they might need to move to
504 : // GetAttributeChangeHint (depending on how, and preferably not).
505 : { &nsGkAtoms::abbr },
506 : { &nsGkAtoms::axis },
507 : { &nsGkAtoms::headers },
508 : { &nsGkAtoms::scope },
509 : #endif
510 : { &nsGkAtoms::width },
511 : { &nsGkAtoms::height },
512 : { nullptr }
513 : };
514 :
515 : static const MappedAttributeEntry* const map[] = {
516 : attributes,
517 : sCommonAttributeMap,
518 : sBackgroundAttributeMap,
519 : };
520 :
521 0 : return FindAttributeDependence(aAttribute, map);
522 : }
523 :
524 : nsMapRuleToAttributesFunc
525 0 : HTMLTableCellElement::GetAttributeMappingFunction() const
526 : {
527 0 : return &MapAttributesIntoRule;
528 : }
529 :
530 : } // namespace dom
531 : } // namespace mozilla
|