summaryrefslogtreecommitdiffstats
path: root/dom/html/HTMLTableCellElement.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'dom/html/HTMLTableCellElement.cpp')
-rw-r--r--dom/html/HTMLTableCellElement.cpp552
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