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