diff options
Diffstat (limited to 'dom/html/HTMLTableCellElement.cpp')
-rw-r--r-- | dom/html/HTMLTableCellElement.cpp | 552 |
1 files changed, 552 insertions, 0 deletions
diff --git a/dom/html/HTMLTableCellElement.cpp b/dom/html/HTMLTableCellElement.cpp new file mode 100644 index 000000000..d00d60400 --- /dev/null +++ b/dom/html/HTMLTableCellElement.cpp @@ -0,0 +1,552 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "mozilla/dom/HTMLTableCellElement.h" +#include "mozilla/dom/HTMLTableElement.h" +#include "mozilla/dom/HTMLTableRowElement.h" +#include "nsMappedAttributes.h" +#include "nsAttrValueInlines.h" +#include "nsRuleData.h" +#include "nsRuleWalker.h" +#include "celldata.h" +#include "mozilla/dom/HTMLTableCellElementBinding.h" + +NS_IMPL_NS_NEW_HTML_ELEMENT(TableCell) + +namespace mozilla { +namespace dom { + +HTMLTableCellElement::~HTMLTableCellElement() +{ +} + +JSObject* +HTMLTableCellElement::WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto) +{ + return HTMLTableCellElementBinding::Wrap(aCx, this, aGivenProto); +} + +NS_IMPL_ISUPPORTS_INHERITED(HTMLTableCellElement, nsGenericHTMLElement, + nsIDOMHTMLTableCellElement) + +NS_IMPL_ELEMENT_CLONE(HTMLTableCellElement) + + +// protected method +HTMLTableRowElement* +HTMLTableCellElement::GetRow() const +{ + return HTMLTableRowElement::FromContentOrNull(GetParent()); +} + +// protected method +HTMLTableElement* +HTMLTableCellElement::GetTable() const +{ + nsIContent *parent = GetParent(); + if (!parent) { + return nullptr; + } + + // parent should be a row. + nsIContent* section = parent->GetParent(); + if (!section) { + return nullptr; + } + + if (section->IsHTMLElement(nsGkAtoms::table)) { + // XHTML, without a row group. + return static_cast<HTMLTableElement*>(section); + } + + // We have a row group. + nsIContent* result = section->GetParent(); + if (result && result->IsHTMLElement(nsGkAtoms::table)) { + return static_cast<HTMLTableElement*>(result); + } + + return nullptr; +} + +int32_t +HTMLTableCellElement::CellIndex() const +{ + HTMLTableRowElement* row = GetRow(); + if (!row) { + return -1; + } + + nsIHTMLCollection* cells = row->Cells(); + if (!cells) { + return -1; + } + + uint32_t numCells = cells->Length(); + for (uint32_t i = 0; i < numCells; i++) { + if (cells->Item(i) == this) { + return i; + } + } + + return -1; +} + +NS_IMETHODIMP +HTMLTableCellElement::GetCellIndex(int32_t* aCellIndex) +{ + *aCellIndex = CellIndex(); + return NS_OK; +} + +NS_IMETHODIMP +HTMLTableCellElement::WalkContentStyleRules(nsRuleWalker* aRuleWalker) +{ + nsresult rv = nsGenericHTMLElement::WalkContentStyleRules(aRuleWalker); + NS_ENSURE_SUCCESS(rv, rv); + + if (HTMLTableElement* table = GetTable()) { + nsMappedAttributes* tableInheritedAttributes = + table->GetAttributesMappedForCell(); + if (tableInheritedAttributes) { + aRuleWalker->Forward(tableInheritedAttributes); + } + } + return NS_OK; +} + +NS_IMETHODIMP +HTMLTableCellElement::SetAbbr(const nsAString& aAbbr) +{ + ErrorResult rv; + SetAbbr(aAbbr, rv); + return rv.StealNSResult(); +} + +NS_IMETHODIMP +HTMLTableCellElement::GetAbbr(nsAString& aAbbr) +{ + DOMString abbr; + GetAbbr(abbr); + abbr.ToString(aAbbr); + return NS_OK; +} + +NS_IMETHODIMP +HTMLTableCellElement::SetAxis(const nsAString& aAxis) +{ + ErrorResult rv; + SetAxis(aAxis, rv); + return rv.StealNSResult(); +} + +NS_IMETHODIMP +HTMLTableCellElement::GetAxis(nsAString& aAxis) +{ + DOMString axis; + GetAxis(axis); + axis.ToString(aAxis); + return NS_OK; +} + +NS_IMETHODIMP +HTMLTableCellElement::SetAlign(const nsAString& aAlign) +{ + ErrorResult rv; + SetAlign(aAlign, rv); + return rv.StealNSResult(); +} + +NS_IMETHODIMP +HTMLTableCellElement::GetAlign(nsAString& aAlign) +{ + DOMString align; + GetAlign(align); + align.ToString(aAlign); + return NS_OK; +} + +NS_IMETHODIMP +HTMLTableCellElement::SetVAlign(const nsAString& aVAlign) +{ + ErrorResult rv; + SetVAlign(aVAlign, rv); + return rv.StealNSResult(); +} + +NS_IMETHODIMP +HTMLTableCellElement::GetVAlign(nsAString& aVAlign) +{ + DOMString vAlign; + GetVAlign(vAlign); + vAlign.ToString(aVAlign); + return NS_OK; +} + +NS_IMETHODIMP +HTMLTableCellElement::SetCh(const nsAString& aCh) +{ + ErrorResult rv; + SetCh(aCh, rv); + return rv.StealNSResult(); +} + +NS_IMETHODIMP +HTMLTableCellElement::GetCh(nsAString& aCh) +{ + DOMString ch; + GetCh(ch); + ch.ToString(aCh); + return NS_OK; +} + +NS_IMETHODIMP +HTMLTableCellElement::SetChOff(const nsAString& aChOff) +{ + ErrorResult rv; + SetChOff(aChOff, rv); + return rv.StealNSResult(); +} + +NS_IMETHODIMP +HTMLTableCellElement::GetChOff(nsAString& aChOff) +{ + DOMString chOff; + GetChOff(chOff); + chOff.ToString(aChOff); + return NS_OK; +} + +NS_IMETHODIMP +HTMLTableCellElement::SetBgColor(const nsAString& aBgColor) +{ + ErrorResult rv; + SetBgColor(aBgColor, rv); + return rv.StealNSResult(); +} + +NS_IMETHODIMP +HTMLTableCellElement::GetBgColor(nsAString& aBgColor) +{ + DOMString bgColor; + GetBgColor(bgColor); + bgColor.ToString(aBgColor); + return NS_OK; +} + +NS_IMETHODIMP +HTMLTableCellElement::SetHeight(const nsAString& aHeight) +{ + ErrorResult rv; + SetHeight(aHeight, rv); + return rv.StealNSResult(); +} + +NS_IMETHODIMP +HTMLTableCellElement::GetHeight(nsAString& aHeight) +{ + DOMString height; + GetHeight(height); + height.ToString(aHeight); + return NS_OK; +} + +NS_IMETHODIMP +HTMLTableCellElement::SetWidth(const nsAString& aWidth) +{ + ErrorResult rv; + SetWidth(aWidth, rv); + return rv.StealNSResult(); +} + +NS_IMETHODIMP +HTMLTableCellElement::GetWidth(nsAString& aWidth) +{ + DOMString width; + GetWidth(width); + width.ToString(aWidth); + return NS_OK; +} + +NS_IMETHODIMP +HTMLTableCellElement::SetNoWrap(bool aNoWrap) +{ + ErrorResult rv; + SetNoWrap(aNoWrap, rv); + return rv.StealNSResult(); +} + +NS_IMETHODIMP +HTMLTableCellElement::GetNoWrap(bool* aNoWrap) +{ + *aNoWrap = NoWrap(); + return NS_OK; +} + +NS_IMETHODIMP +HTMLTableCellElement::SetScope(const nsAString& aScope) +{ + ErrorResult rv; + SetScope(aScope, rv); + return rv.StealNSResult(); +} + +NS_IMETHODIMP +HTMLTableCellElement::GetScope(nsAString& aScope) +{ + DOMString scope; + GetScope(scope); + scope.ToString(aScope); + return NS_OK; +} + +NS_IMETHODIMP +HTMLTableCellElement::SetHeaders(const nsAString& aHeaders) +{ + ErrorResult rv; + SetHeaders(aHeaders, rv); + return rv.StealNSResult(); +} + +NS_IMETHODIMP +HTMLTableCellElement::GetHeaders(nsAString& aHeaders) +{ + DOMString headers; + GetHeaders(headers); + headers.ToString(aHeaders); + return NS_OK; +} + +NS_IMETHODIMP +HTMLTableCellElement::SetColSpan(int32_t aColSpan) +{ + ErrorResult rv; + SetColSpan(aColSpan, rv); + return rv.StealNSResult(); +} + +NS_IMETHODIMP +HTMLTableCellElement::GetColSpan(int32_t* aColSpan) +{ + *aColSpan = ColSpan(); + return NS_OK; +} + +NS_IMETHODIMP +HTMLTableCellElement::SetRowSpan(int32_t aRowSpan) +{ + ErrorResult rv; + SetRowSpan(aRowSpan, rv); + return rv.StealNSResult(); +} + +NS_IMETHODIMP +HTMLTableCellElement::GetRowSpan(int32_t* aRowSpan) +{ + *aRowSpan = RowSpan(); + return NS_OK; +} + +void +HTMLTableCellElement::GetAlign(DOMString& aValue) +{ + if (!GetAttr(kNameSpaceID_None, nsGkAtoms::align, aValue)) { + // There's no align attribute, ask the row for the alignment. + HTMLTableRowElement* row = GetRow(); + if (row) { + row->GetAlign(aValue); + } + } +} + +static const nsAttrValue::EnumTable kCellScopeTable[] = { + { "row", NS_STYLE_CELL_SCOPE_ROW }, + { "col", NS_STYLE_CELL_SCOPE_COL }, + { "rowgroup", NS_STYLE_CELL_SCOPE_ROWGROUP }, + { "colgroup", NS_STYLE_CELL_SCOPE_COLGROUP }, + { nullptr, 0 } +}; + +void +HTMLTableCellElement::GetScope(DOMString& aScope) +{ + GetEnumAttr(nsGkAtoms::scope, nullptr, aScope); +} + +bool +HTMLTableCellElement::ParseAttribute(int32_t aNamespaceID, + nsIAtom* aAttribute, + const nsAString& aValue, + nsAttrValue& aResult) +{ + if (aNamespaceID == kNameSpaceID_None) { + /* ignore these attributes, stored simply as strings + abbr, axis, ch, headers + */ + if (aAttribute == nsGkAtoms::charoff) { + /* attributes that resolve to integers with a min of 0 */ + return aResult.ParseIntWithBounds(aValue, 0); + } + if (aAttribute == nsGkAtoms::colspan) { + bool res = aResult.ParseIntWithBounds(aValue, -1); + if (res) { + int32_t val = aResult.GetIntegerValue(); + // reset large colspan values as IE and opera do + if (val > MAX_COLSPAN || val <= 0) { + aResult.SetTo(1, &aValue); + } + } + return res; + } + if (aAttribute == nsGkAtoms::rowspan) { + bool res = aResult.ParseIntWithBounds(aValue, -1, MAX_ROWSPAN); + if (res) { + int32_t val = aResult.GetIntegerValue(); + // quirks mode does not honor the special html 4 value of 0 + if (val < 0 || (0 == val && InNavQuirksMode(OwnerDoc()))) { + aResult.SetTo(1, &aValue); + } + } + return res; + } + if (aAttribute == nsGkAtoms::height) { + return aResult.ParseSpecialIntValue(aValue); + } + if (aAttribute == nsGkAtoms::width) { + return aResult.ParseSpecialIntValue(aValue); + } + if (aAttribute == nsGkAtoms::align) { + return ParseTableCellHAlignValue(aValue, aResult); + } + if (aAttribute == nsGkAtoms::bgcolor) { + return aResult.ParseColor(aValue); + } + if (aAttribute == nsGkAtoms::scope) { + return aResult.ParseEnumValue(aValue, kCellScopeTable, false); + } + if (aAttribute == nsGkAtoms::valign) { + return ParseTableVAlignValue(aValue, aResult); + } + } + + return nsGenericHTMLElement::ParseBackgroundAttribute(aNamespaceID, + aAttribute, aValue, + aResult) || + nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue, + aResult); +} + +void +HTMLTableCellElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes, + nsRuleData* aData) +{ + if (aData->mSIDs & NS_STYLE_INHERIT_BIT(Position)) { + // width: value + nsCSSValue* width = aData->ValueForWidth(); + if (width->GetUnit() == eCSSUnit_Null) { + const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::width); + if (value && value->Type() == nsAttrValue::eInteger) { + if (value->GetIntegerValue() > 0) + width->SetFloatValue((float)value->GetIntegerValue(), eCSSUnit_Pixel); + // else 0 implies auto for compatibility. + } + else if (value && value->Type() == nsAttrValue::ePercent) { + if (value->GetPercentValue() > 0.0f) + width->SetPercentValue(value->GetPercentValue()); + // else 0 implies auto for compatibility + } + } + + // height: value + nsCSSValue* height = aData->ValueForHeight(); + if (height->GetUnit() == eCSSUnit_Null) { + const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::height); + if (value && value->Type() == nsAttrValue::eInteger) { + if (value->GetIntegerValue() > 0) + height->SetFloatValue((float)value->GetIntegerValue(), eCSSUnit_Pixel); + // else 0 implies auto for compatibility. + } + else if (value && value->Type() == nsAttrValue::ePercent) { + if (value->GetPercentValue() > 0.0f) + height->SetPercentValue(value->GetPercentValue()); + // else 0 implies auto for compatibility + } + } + } + if (aData->mSIDs & NS_STYLE_INHERIT_BIT(Text)) { + nsCSSValue* textAlign = aData->ValueForTextAlign(); + if (textAlign->GetUnit() == eCSSUnit_Null) { + // align: enum + const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::align); + if (value && value->Type() == nsAttrValue::eEnum) + textAlign->SetIntValue(value->GetEnumValue(), eCSSUnit_Enumerated); + } + + nsCSSValue* whiteSpace = aData->ValueForWhiteSpace(); + if (whiteSpace->GetUnit() == eCSSUnit_Null) { + // nowrap: enum + if (aAttributes->GetAttr(nsGkAtoms::nowrap)) { + // See if our width is not a nonzero integer width. + const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::width); + nsCompatibility mode = aData->mPresContext->CompatibilityMode(); + if (!value || value->Type() != nsAttrValue::eInteger || + value->GetIntegerValue() == 0 || + eCompatibility_NavQuirks != mode) { + whiteSpace->SetIntValue(NS_STYLE_WHITESPACE_NOWRAP, eCSSUnit_Enumerated); + } + } + } + } + if (aData->mSIDs & NS_STYLE_INHERIT_BIT(Display)) { + nsCSSValue* verticalAlign = aData->ValueForVerticalAlign(); + if (verticalAlign->GetUnit() == eCSSUnit_Null) { + // valign: enum + const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::valign); + if (value && value->Type() == nsAttrValue::eEnum) + verticalAlign->SetIntValue(value->GetEnumValue(), eCSSUnit_Enumerated); + } + } + + nsGenericHTMLElement::MapBackgroundAttributesInto(aAttributes, aData); + nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aData); +} + +NS_IMETHODIMP_(bool) +HTMLTableCellElement::IsAttributeMapped(const nsIAtom* aAttribute) const +{ + static const MappedAttributeEntry attributes[] = { + { &nsGkAtoms::align }, + { &nsGkAtoms::valign }, + { &nsGkAtoms::nowrap }, +#if 0 + // XXXldb If these are implemented, they might need to move to + // GetAttributeChangeHint (depending on how, and preferably not). + { &nsGkAtoms::abbr }, + { &nsGkAtoms::axis }, + { &nsGkAtoms::headers }, + { &nsGkAtoms::scope }, +#endif + { &nsGkAtoms::width }, + { &nsGkAtoms::height }, + { nullptr } + }; + + static const MappedAttributeEntry* const map[] = { + attributes, + sCommonAttributeMap, + sBackgroundAttributeMap, + }; + + return FindAttributeDependence(aAttribute, map); +} + +nsMapRuleToAttributesFunc +HTMLTableCellElement::GetAttributeMappingFunction() const +{ + return &MapAttributesIntoRule; +} + +} // namespace dom +} // namespace mozilla |