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