HTMLTableRowElement.cpp 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329
  1. /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
  2. /* This Source Code Form is subject to the terms of the Mozilla Public
  3. * License, v. 2.0. If a copy of the MPL was not distributed with this
  4. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  5. #include "mozilla/dom/HTMLTableRowElement.h"
  6. #include "mozilla/dom/HTMLTableElement.h"
  7. #include "nsMappedAttributes.h"
  8. #include "nsAttrValueInlines.h"
  9. #include "nsRuleData.h"
  10. #include "mozilla/dom/BindingUtils.h"
  11. #include "mozilla/dom/HTMLTableRowElementBinding.h"
  12. #include "nsContentList.h"
  13. #include "nsContentUtils.h"
  14. NS_IMPL_NS_NEW_HTML_ELEMENT(TableRow)
  15. namespace mozilla {
  16. namespace dom {
  17. HTMLTableRowElement::~HTMLTableRowElement()
  18. {
  19. }
  20. JSObject*
  21. HTMLTableRowElement::WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto)
  22. {
  23. return HTMLTableRowElementBinding::Wrap(aCx, this, aGivenProto);
  24. }
  25. NS_IMPL_CYCLE_COLLECTION_CLASS(HTMLTableRowElement)
  26. NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(HTMLTableRowElement,
  27. nsGenericHTMLElement)
  28. NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCells)
  29. NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
  30. NS_IMPL_ADDREF_INHERITED(HTMLTableRowElement, Element)
  31. NS_IMPL_RELEASE_INHERITED(HTMLTableRowElement, Element)
  32. // QueryInterface implementation for HTMLTableRowElement
  33. NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(HTMLTableRowElement)
  34. NS_INTERFACE_MAP_END_INHERITING(nsGenericHTMLElement)
  35. NS_IMPL_ELEMENT_CLONE(HTMLTableRowElement)
  36. // protected method
  37. HTMLTableSectionElement*
  38. HTMLTableRowElement::GetSection() const
  39. {
  40. nsIContent* parent = GetParent();
  41. if (parent &&
  42. parent->IsAnyOfHTMLElements(nsGkAtoms::thead,
  43. nsGkAtoms::tbody,
  44. nsGkAtoms::tfoot)) {
  45. return static_cast<HTMLTableSectionElement*>(parent);
  46. }
  47. return nullptr;
  48. }
  49. // protected method
  50. HTMLTableElement*
  51. HTMLTableRowElement::GetTable() const
  52. {
  53. nsIContent* parent = GetParent();
  54. if (!parent) {
  55. return nullptr;
  56. }
  57. // We may not be in a section
  58. HTMLTableElement* table = HTMLTableElement::FromContent(parent);
  59. if (table) {
  60. return table;
  61. }
  62. return HTMLTableElement::FromContentOrNull(parent->GetParent());
  63. }
  64. int32_t
  65. HTMLTableRowElement::RowIndex() const
  66. {
  67. HTMLTableElement* table = GetTable();
  68. if (!table) {
  69. return -1;
  70. }
  71. nsIHTMLCollection* rows = table->Rows();
  72. uint32_t numRows = rows->Length();
  73. for (uint32_t i = 0; i < numRows; i++) {
  74. if (rows->GetElementAt(i) == this) {
  75. return i;
  76. }
  77. }
  78. return -1;
  79. }
  80. int32_t
  81. HTMLTableRowElement::SectionRowIndex() const
  82. {
  83. HTMLTableSectionElement* section = GetSection();
  84. if (!section) {
  85. return -1;
  86. }
  87. nsCOMPtr<nsIHTMLCollection> coll = section->Rows();
  88. uint32_t numRows = coll->Length();
  89. for (uint32_t i = 0; i < numRows; i++) {
  90. if (coll->GetElementAt(i) == this) {
  91. return i;
  92. }
  93. }
  94. return -1;
  95. }
  96. static bool
  97. IsCell(Element *aElement, int32_t aNamespaceID,
  98. nsIAtom* aAtom, void *aData)
  99. {
  100. return aElement->IsAnyOfHTMLElements(nsGkAtoms::td, nsGkAtoms::th);
  101. }
  102. nsIHTMLCollection*
  103. HTMLTableRowElement::Cells()
  104. {
  105. if (!mCells) {
  106. mCells = new nsContentList(this,
  107. IsCell,
  108. nullptr, // destroy func
  109. nullptr, // closure data
  110. false,
  111. nullptr,
  112. kNameSpaceID_XHTML,
  113. false);
  114. }
  115. return mCells;
  116. }
  117. already_AddRefed<nsGenericHTMLElement>
  118. HTMLTableRowElement::InsertCell(int32_t aIndex,
  119. ErrorResult& aError)
  120. {
  121. if (aIndex < -1) {
  122. aError.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
  123. return nullptr;
  124. }
  125. // Make sure mCells is initialized.
  126. nsIHTMLCollection* cells = Cells();
  127. NS_ASSERTION(mCells, "How did that happen?");
  128. nsCOMPtr<nsINode> nextSibling;
  129. // -1 means append, so should use null nextSibling
  130. if (aIndex != -1) {
  131. nextSibling = cells->Item(aIndex);
  132. // Check whether we're inserting past end of list. We want to avoid doing
  133. // this unless we really have to, since this has to walk all our kids. If
  134. // we have a nextSibling, we're clearly not past end of list.
  135. if (!nextSibling) {
  136. uint32_t cellCount = cells->Length();
  137. if (aIndex > int32_t(cellCount)) {
  138. aError.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
  139. return nullptr;
  140. }
  141. }
  142. }
  143. // create the cell
  144. RefPtr<mozilla::dom::NodeInfo> nodeInfo;
  145. nsContentUtils::NameChanged(mNodeInfo, nsGkAtoms::td,
  146. getter_AddRefs(nodeInfo));
  147. RefPtr<nsGenericHTMLElement> cell =
  148. NS_NewHTMLTableCellElement(nodeInfo.forget());
  149. if (!cell) {
  150. aError.Throw(NS_ERROR_OUT_OF_MEMORY);
  151. return nullptr;
  152. }
  153. nsINode::InsertBefore(*cell, nextSibling, aError);
  154. return cell.forget();
  155. }
  156. void
  157. HTMLTableRowElement::DeleteCell(int32_t aValue, ErrorResult& aError)
  158. {
  159. if (aValue < -1) {
  160. aError.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
  161. return;
  162. }
  163. nsIHTMLCollection* cells = Cells();
  164. uint32_t refIndex;
  165. if (aValue == -1) {
  166. refIndex = cells->Length();
  167. if (refIndex == 0) {
  168. return;
  169. }
  170. --refIndex;
  171. }
  172. else {
  173. refIndex = (uint32_t)aValue;
  174. }
  175. nsCOMPtr<nsINode> cell = cells->Item(refIndex);
  176. if (!cell) {
  177. aError.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
  178. return;
  179. }
  180. nsINode::RemoveChild(*cell, aError);
  181. }
  182. bool
  183. HTMLTableRowElement::ParseAttribute(int32_t aNamespaceID,
  184. nsIAtom* aAttribute,
  185. const nsAString& aValue,
  186. nsAttrValue& aResult)
  187. {
  188. /*
  189. * ignore these attributes, stored simply as strings
  190. *
  191. * ch
  192. */
  193. if (aNamespaceID == kNameSpaceID_None) {
  194. if (aAttribute == nsGkAtoms::charoff) {
  195. return aResult.ParseIntWithBounds(aValue, 0);
  196. }
  197. if (aAttribute == nsGkAtoms::height) {
  198. return aResult.ParseSpecialIntValue(aValue);
  199. }
  200. if (aAttribute == nsGkAtoms::width) {
  201. return aResult.ParseSpecialIntValue(aValue);
  202. }
  203. if (aAttribute == nsGkAtoms::align) {
  204. return ParseTableCellHAlignValue(aValue, aResult);
  205. }
  206. if (aAttribute == nsGkAtoms::bgcolor) {
  207. return aResult.ParseColor(aValue);
  208. }
  209. if (aAttribute == nsGkAtoms::valign) {
  210. return ParseTableVAlignValue(aValue, aResult);
  211. }
  212. }
  213. return nsGenericHTMLElement::ParseBackgroundAttribute(aNamespaceID,
  214. aAttribute, aValue,
  215. aResult) ||
  216. nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
  217. aResult);
  218. }
  219. void
  220. HTMLTableRowElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
  221. nsRuleData* aData)
  222. {
  223. if (aData->mSIDs & NS_STYLE_INHERIT_BIT(Position)) {
  224. // height: value
  225. nsCSSValue* height = aData->ValueForHeight();
  226. if (height->GetUnit() == eCSSUnit_Null) {
  227. const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::height);
  228. if (value && value->Type() == nsAttrValue::eInteger)
  229. height->SetFloatValue((float)value->GetIntegerValue(), eCSSUnit_Pixel);
  230. else if (value && value->Type() == nsAttrValue::ePercent)
  231. height->SetPercentValue(value->GetPercentValue());
  232. }
  233. }
  234. if (aData->mSIDs & NS_STYLE_INHERIT_BIT(Text)) {
  235. nsCSSValue* textAlign = aData->ValueForTextAlign();
  236. if (textAlign->GetUnit() == eCSSUnit_Null) {
  237. // align: enum
  238. const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::align);
  239. if (value && value->Type() == nsAttrValue::eEnum)
  240. textAlign->SetIntValue(value->GetEnumValue(), eCSSUnit_Enumerated);
  241. }
  242. }
  243. if (aData->mSIDs & NS_STYLE_INHERIT_BIT(Display)) {
  244. nsCSSValue* verticalAlign = aData->ValueForVerticalAlign();
  245. if (verticalAlign->GetUnit() == eCSSUnit_Null) {
  246. // valign: enum
  247. const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::valign);
  248. if (value && value->Type() == nsAttrValue::eEnum)
  249. verticalAlign->SetIntValue(value->GetEnumValue(), eCSSUnit_Enumerated);
  250. }
  251. }
  252. nsGenericHTMLElement::MapBackgroundAttributesInto(aAttributes, aData);
  253. nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aData);
  254. }
  255. NS_IMETHODIMP_(bool)
  256. HTMLTableRowElement::IsAttributeMapped(const nsIAtom* aAttribute) const
  257. {
  258. static const MappedAttributeEntry attributes[] = {
  259. { &nsGkAtoms::align },
  260. { &nsGkAtoms::valign },
  261. { &nsGkAtoms::height },
  262. { nullptr }
  263. };
  264. static const MappedAttributeEntry* const map[] = {
  265. attributes,
  266. sCommonAttributeMap,
  267. sBackgroundAttributeMap,
  268. };
  269. return FindAttributeDependence(aAttribute, map);
  270. }
  271. nsMapRuleToAttributesFunc
  272. HTMLTableRowElement::GetAttributeMappingFunction() const
  273. {
  274. return &MapAttributesIntoRule;
  275. }
  276. } // namespace dom
  277. } // namespace mozilla