blob: 1adbb3e041e9adf3d751d0db76312f3dfda306f8 [file] [log] [blame]
darin@apple.comeb701802008-01-03 01:25:51 +00001/*
eseidel787da6b2006-05-12 19:44:03 +00002 * Copyright (C) 1997 Martin Jones (mjones@kde.org)
3 * (C) 1997 Torben Weis (weis@kde.org)
4 * (C) 1998 Waldo Bastian (bastian@kde.org)
5 * (C) 1999 Lars Knoll (knoll@kde.org)
6 * (C) 1999 Antti Koivisto (koivisto@kde.org)
kling@webkit.orge72793e2011-12-24 21:24:59 +00007 * Copyright (C) 2003, 2004, 2005, 2006, 2008, 2010, 2011 Apple Inc. All rights reserved.
eseidel787da6b2006-05-12 19:44:03 +00008 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Library General Public
11 * License as published by the Free Software Foundation; either
12 * version 2 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Library General Public License for more details.
18 *
19 * You should have received a copy of the GNU Library General Public License
20 * along with this library; see the file COPYING.LIB. If not, write to
ddkilzerc8eccec2007-09-26 02:29:57 +000021 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22 * Boston, MA 02110-1301, USA.
eseidel787da6b2006-05-12 19:44:03 +000023 */
darin@apple.comeb701802008-01-03 01:25:51 +000024
eseidel787da6b2006-05-12 19:44:03 +000025#include "config.h"
26#include "HTMLTableElement.h"
27
weinig@apple.comc3608932010-05-19 17:48:06 +000028#include "Attribute.h"
kling@webkit.org8b0e8432012-02-11 19:29:49 +000029#include "CSSImageValue.h"
eseidel787da6b2006-05-12 19:44:03 +000030#include "CSSPropertyNames.h"
eseidelb3f42132006-05-16 02:08:51 +000031#include "CSSStyleSheet.h"
eseidel787da6b2006-05-12 19:44:03 +000032#include "CSSValueKeywords.h"
kling@webkit.org2340d5e2012-02-25 17:43:32 +000033#include "CSSValuePool.h"
eseidel787da6b2006-05-12 19:44:03 +000034#include "ExceptionCode.h"
eseidel787da6b2006-05-12 19:44:03 +000035#include "HTMLNames.h"
darin@apple.com7b7981b2010-10-01 00:04:02 +000036#include "HTMLParserIdioms.h"
eseidel787da6b2006-05-12 19:44:03 +000037#include "HTMLTableCaptionElement.h"
darin@apple.comeb701802008-01-03 01:25:51 +000038#include "HTMLTableRowElement.h"
darin@apple.com9a925fa2009-05-04 18:00:34 +000039#include "HTMLTableRowsCollection.h"
eseidel787da6b2006-05-12 19:44:03 +000040#include "HTMLTableSectionElement.h"
41#include "RenderTable.h"
hyattf2cfbe02007-05-24 18:26:21 +000042#include "Text.h"
eseidel787da6b2006-05-12 19:44:03 +000043
44namespace WebCore {
45
46using namespace HTMLNames;
47
darin@apple.com877ce5b2010-05-28 15:38:58 +000048HTMLTableElement::HTMLTableElement(const QualifiedName& tagName, Document* document)
49 : HTMLElement(tagName, document)
hyatteef21e02006-09-17 07:57:56 +000050 , m_borderAttr(false)
51 , m_borderColorAttr(false)
52 , m_frameAttr(false)
53 , m_rulesAttr(UnsetRules)
54 , m_padding(1)
eseidel787da6b2006-05-12 19:44:03 +000055{
jchaffraix@webkit.org94d95b02008-12-04 22:39:05 +000056 ASSERT(hasTagName(tableTag));
eseidel787da6b2006-05-12 19:44:03 +000057}
58
darin@apple.com877ce5b2010-05-28 15:38:58 +000059PassRefPtr<HTMLTableElement> HTMLTableElement::create(Document* document)
60{
darin@apple.comf190b3d2010-06-16 23:07:32 +000061 return adoptRef(new HTMLTableElement(tableTag, document));
darin@apple.com877ce5b2010-05-28 15:38:58 +000062}
63
64PassRefPtr<HTMLTableElement> HTMLTableElement::create(const QualifiedName& tagName, Document* document)
65{
darin@apple.comf190b3d2010-06-16 23:07:32 +000066 return adoptRef(new HTMLTableElement(tagName, document));
darin@apple.com877ce5b2010-05-28 15:38:58 +000067}
68
darin@apple.comeb701802008-01-03 01:25:51 +000069HTMLTableCaptionElement* HTMLTableElement::caption() const
eseidel787da6b2006-05-12 19:44:03 +000070{
darin@apple.comeb701802008-01-03 01:25:51 +000071 for (Node* child = firstChild(); child; child = child->nextSibling()) {
72 if (child->hasTagName(captionTag))
73 return static_cast<HTMLTableCaptionElement*>(child);
eseidel787da6b2006-05-12 19:44:03 +000074 }
darin@apple.comeb701802008-01-03 01:25:51 +000075 return 0;
76}
77
78void HTMLTableElement::setCaption(PassRefPtr<HTMLTableCaptionElement> newCaption, ExceptionCode& ec)
79{
80 deleteCaption();
81 insertBefore(newCaption, firstChild(), ec);
82}
83
84HTMLTableSectionElement* HTMLTableElement::tHead() const
85{
86 for (Node* child = firstChild(); child; child = child->nextSibling()) {
87 if (child->hasTagName(theadTag))
88 return static_cast<HTMLTableSectionElement*>(child);
89 }
90 return 0;
91}
92
93void HTMLTableElement::setTHead(PassRefPtr<HTMLTableSectionElement> newHead, ExceptionCode& ec)
94{
95 deleteTHead();
96
97 Node* child;
98 for (child = firstChild(); child; child = child->nextSibling())
99 if (child->isElementNode() && !child->hasTagName(captionTag) && !child->hasTagName(colgroupTag))
100 break;
101
102 insertBefore(newHead, child, ec);
103}
104
105HTMLTableSectionElement* HTMLTableElement::tFoot() const
106{
107 for (Node* child = firstChild(); child; child = child->nextSibling()) {
108 if (child->hasTagName(tfootTag))
109 return static_cast<HTMLTableSectionElement*>(child);
110 }
111 return 0;
112}
113
114void HTMLTableElement::setTFoot(PassRefPtr<HTMLTableSectionElement> newFoot, ExceptionCode& ec)
115{
116 deleteTFoot();
117
118 Node* child;
119 for (child = firstChild(); child; child = child->nextSibling())
120 if (child->isElementNode() && !child->hasTagName(captionTag) && !child->hasTagName(colgroupTag) && !child->hasTagName(theadTag))
121 break;
122
123 insertBefore(newFoot, child, ec);
124}
125
126PassRefPtr<HTMLElement> HTMLTableElement::createTHead()
127{
128 if (HTMLTableSectionElement* existingHead = tHead())
129 return existingHead;
darin@apple.com877ce5b2010-05-28 15:38:58 +0000130 RefPtr<HTMLTableSectionElement> head = HTMLTableSectionElement::create(theadTag, document());
darin@apple.comeb701802008-01-03 01:25:51 +0000131 ExceptionCode ec;
132 setTHead(head, ec);
133 return head.release();
eseidel787da6b2006-05-12 19:44:03 +0000134}
135
136void HTMLTableElement::deleteTHead()
137{
darin@apple.comeb701802008-01-03 01:25:51 +0000138 ExceptionCode ec;
139 removeChild(tHead(), ec);
eseidel787da6b2006-05-12 19:44:03 +0000140}
141
darin@apple.comeb701802008-01-03 01:25:51 +0000142PassRefPtr<HTMLElement> HTMLTableElement::createTFoot()
eseidel787da6b2006-05-12 19:44:03 +0000143{
darin@apple.comeb701802008-01-03 01:25:51 +0000144 if (HTMLTableSectionElement* existingFoot = tFoot())
145 return existingFoot;
darin@apple.com877ce5b2010-05-28 15:38:58 +0000146 RefPtr<HTMLTableSectionElement> foot = HTMLTableSectionElement::create(tfootTag, document());
darin@apple.comeb701802008-01-03 01:25:51 +0000147 ExceptionCode ec;
148 setTFoot(foot, ec);
149 return foot.release();
eseidel787da6b2006-05-12 19:44:03 +0000150}
151
152void HTMLTableElement::deleteTFoot()
153{
darin@apple.comeb701802008-01-03 01:25:51 +0000154 ExceptionCode ec;
155 removeChild(tFoot(), ec);
eseidel787da6b2006-05-12 19:44:03 +0000156}
157
alexis.menard@openbossa.org83fc9ae2012-04-25 02:11:26 +0000158PassRefPtr<HTMLElement> HTMLTableElement::createTBody()
159{
160 RefPtr<HTMLTableSectionElement> body = HTMLTableSectionElement::create(tbodyTag, document());
161 Node* referenceElement = lastBody() ? lastBody()->nextSibling() : 0;
162 insertBefore(body, referenceElement, ASSERT_NO_EXCEPTION);
163 return body.release();
164}
165
darin@apple.comeb701802008-01-03 01:25:51 +0000166PassRefPtr<HTMLElement> HTMLTableElement::createCaption()
eseidel787da6b2006-05-12 19:44:03 +0000167{
darin@apple.comeb701802008-01-03 01:25:51 +0000168 if (HTMLTableCaptionElement* existingCaption = caption())
169 return existingCaption;
darin@apple.com8faae442010-05-28 04:21:55 +0000170 RefPtr<HTMLTableCaptionElement> caption = HTMLTableCaptionElement::create(captionTag, document());
darin@apple.comeb701802008-01-03 01:25:51 +0000171 ExceptionCode ec;
172 setCaption(caption, ec);
173 return caption.release();
eseidel787da6b2006-05-12 19:44:03 +0000174}
175
176void HTMLTableElement::deleteCaption()
177{
darin@apple.comeb701802008-01-03 01:25:51 +0000178 ExceptionCode ec;
179 removeChild(caption(), ec);
180}
181
182HTMLTableSectionElement* HTMLTableElement::lastBody() const
183{
184 for (Node* child = lastChild(); child; child = child->previousSibling()) {
185 if (child->hasTagName(tbodyTag))
186 return static_cast<HTMLTableSectionElement*>(child);
eseidel787da6b2006-05-12 19:44:03 +0000187 }
darin@apple.comeb701802008-01-03 01:25:51 +0000188 return 0;
eseidel787da6b2006-05-12 19:44:03 +0000189}
190
darinf0d19342007-05-01 19:59:53 +0000191PassRefPtr<HTMLElement> HTMLTableElement::insertRow(int index, ExceptionCode& ec)
eseidel787da6b2006-05-12 19:44:03 +0000192{
darin@apple.comeb701802008-01-03 01:25:51 +0000193 if (index < -1) {
eseidel787da6b2006-05-12 19:44:03 +0000194 ec = INDEX_SIZE_ERR;
darinf0d19342007-05-01 19:59:53 +0000195 return 0;
eseidel787da6b2006-05-12 19:44:03 +0000196 }
darin@apple.comeb701802008-01-03 01:25:51 +0000197
inferno@chromium.org50a2ce72012-03-01 18:19:03 +0000198 RefPtr<Node> protectFromMutationEvents(this);
199
200 RefPtr<HTMLTableRowElement> lastRow = 0;
201 RefPtr<HTMLTableRowElement> row = 0;
darin@apple.comeb701802008-01-03 01:25:51 +0000202 if (index == -1)
203 lastRow = HTMLTableRowsCollection::lastRow(this);
204 else {
205 for (int i = 0; i <= index; ++i) {
inferno@chromium.org50a2ce72012-03-01 18:19:03 +0000206 row = HTMLTableRowsCollection::rowAfter(this, lastRow.get());
darin@apple.comeb701802008-01-03 01:25:51 +0000207 if (!row) {
208 if (i != index) {
209 ec = INDEX_SIZE_ERR;
210 return 0;
211 }
212 break;
213 }
214 lastRow = row;
215 }
216 }
217
inferno@chromium.org50a2ce72012-03-01 18:19:03 +0000218 RefPtr<ContainerNode> parent;
darin@apple.comeb701802008-01-03 01:25:51 +0000219 if (lastRow)
dglazkov@chromium.orge43caa72010-11-18 00:20:10 +0000220 parent = row ? row->parentNode() : lastRow->parentNode();
darin@apple.comeb701802008-01-03 01:25:51 +0000221 else {
222 parent = lastBody();
223 if (!parent) {
darin@apple.com877ce5b2010-05-28 15:38:58 +0000224 RefPtr<HTMLTableSectionElement> newBody = HTMLTableSectionElement::create(tbodyTag, document());
225 RefPtr<HTMLTableRowElement> newRow = HTMLTableRowElement::create(document());
darin@apple.comeb701802008-01-03 01:25:51 +0000226 newBody->appendChild(newRow, ec);
227 appendChild(newBody.release(), ec);
228 return newRow.release();
229 }
230 }
231
darin@apple.com877ce5b2010-05-28 15:38:58 +0000232 RefPtr<HTMLTableRowElement> newRow = HTMLTableRowElement::create(document());
inferno@chromium.org50a2ce72012-03-01 18:19:03 +0000233 parent->insertBefore(newRow, row.get(), ec);
darin@apple.comeb701802008-01-03 01:25:51 +0000234 return newRow.release();
eseidel787da6b2006-05-12 19:44:03 +0000235}
236
237void HTMLTableElement::deleteRow(int index, ExceptionCode& ec)
238{
darin@apple.comeb701802008-01-03 01:25:51 +0000239 HTMLTableRowElement* row = 0;
240 if (index == -1)
241 row = HTMLTableRowsCollection::lastRow(this);
242 else {
243 for (int i = 0; i <= index; ++i) {
244 row = HTMLTableRowsCollection::rowAfter(this, row);
245 if (!row)
246 break;
eseidel787da6b2006-05-12 19:44:03 +0000247 }
eseidel787da6b2006-05-12 19:44:03 +0000248 }
darin@apple.comeb701802008-01-03 01:25:51 +0000249 if (!row) {
eseidel787da6b2006-05-12 19:44:03 +0000250 ec = INDEX_SIZE_ERR;
darin@apple.comeb701802008-01-03 01:25:51 +0000251 return;
252 }
253 row->remove(ec);
eseidel787da6b2006-05-12 19:44:03 +0000254}
255
rwlbuisda67f4e2007-08-25 16:57:13 +0000256static inline bool isTableCellAncestor(Node* n)
257{
258 return n->hasTagName(theadTag) || n->hasTagName(tbodyTag) ||
259 n->hasTagName(tfootTag) || n->hasTagName(trTag) ||
260 n->hasTagName(thTag);
261}
262
263static bool setTableCellsChanged(Node* n)
264{
265 ASSERT(n);
266 bool cellChanged = false;
267
268 if (n->hasTagName(tdTag))
269 cellChanged = true;
270 else if (isTableCellAncestor(n)) {
271 for (Node* child = n->firstChild(); child; child = child->nextSibling())
272 cellChanged |= setTableCellsChanged(child);
273 }
274
275 if (cellChanged)
hyatt@apple.comf6d72f32009-04-10 00:05:02 +0000276 n->setNeedsStyleRecalc();
rwlbuisda67f4e2007-08-25 16:57:13 +0000277
278 return cellChanged;
279}
280
kling@webkit.org8b0e8432012-02-11 19:29:49 +0000281static bool getBordersFromFrameAttributeValue(const AtomicString& value, bool& borderTop, bool& borderRight, bool& borderBottom, bool& borderLeft)
282{
283 borderTop = false;
284 borderRight = false;
285 borderBottom = false;
286 borderLeft = false;
287
288 if (equalIgnoringCase(value, "above"))
289 borderTop = true;
290 else if (equalIgnoringCase(value, "below"))
291 borderBottom = true;
292 else if (equalIgnoringCase(value, "hsides"))
293 borderTop = borderBottom = true;
294 else if (equalIgnoringCase(value, "vsides"))
295 borderLeft = borderRight = true;
296 else if (equalIgnoringCase(value, "lhs"))
297 borderLeft = true;
298 else if (equalIgnoringCase(value, "rhs"))
299 borderRight = true;
300 else if (equalIgnoringCase(value, "box") || equalIgnoringCase(value, "border"))
301 borderTop = borderBottom = borderLeft = borderRight = true;
302 else if (!equalIgnoringCase(value, "void"))
303 return false;
304 return true;
305}
306
kling@webkit.org260fca82012-05-16 00:34:16 +0000307void HTMLTableElement::collectStyleForAttribute(const Attribute& attribute, StylePropertySet* style)
kling@webkit.org8b0e8432012-02-11 19:29:49 +0000308{
kling@webkit.org260fca82012-05-16 00:34:16 +0000309 if (attribute.name() == widthAttr)
310 addHTMLLengthToStyle(style, CSSPropertyWidth, attribute.value());
311 else if (attribute.name() == heightAttr)
312 addHTMLLengthToStyle(style, CSSPropertyHeight, attribute.value());
313 else if (attribute.name() == borderAttr) {
314 int borderWidth = attribute.isEmpty() ? 1 : attribute.value().toInt();
kling@webkit.orgec5657f2012-02-24 11:21:22 +0000315 addPropertyToAttributeStyle(style, CSSPropertyBorderWidth, borderWidth, CSSPrimitiveValue::CSS_PX);
kling@webkit.org260fca82012-05-16 00:34:16 +0000316 } else if (attribute.name() == bordercolorAttr) {
317 if (!attribute.isEmpty())
318 addHTMLColorToStyle(style, CSSPropertyBorderColor, attribute.value());
319 } else if (attribute.name() == bgcolorAttr)
320 addHTMLColorToStyle(style, CSSPropertyBackgroundColor, attribute.value());
321 else if (attribute.name() == backgroundAttr) {
322 String url = stripLeadingAndTrailingHTMLSpaces(attribute.value());
kling@webkit.org8b0e8432012-02-11 19:29:49 +0000323 if (!url.isEmpty())
324 style->setProperty(CSSProperty(CSSPropertyBackgroundImage, CSSImageValue::create(document()->completeURL(url).string())));
kling@webkit.org260fca82012-05-16 00:34:16 +0000325 } else if (attribute.name() == valignAttr) {
326 if (!attribute.isEmpty())
327 addPropertyToAttributeStyle(style, CSSPropertyVerticalAlign, attribute.value());
328 } else if (attribute.name() == cellspacingAttr) {
329 if (!attribute.isEmpty())
330 addHTMLLengthToStyle(style, CSSPropertyBorderSpacing, attribute.value());
331 } else if (attribute.name() == vspaceAttr) {
332 addHTMLLengthToStyle(style, CSSPropertyMarginTop, attribute.value());
333 addHTMLLengthToStyle(style, CSSPropertyMarginBottom, attribute.value());
334 } else if (attribute.name() == hspaceAttr) {
335 addHTMLLengthToStyle(style, CSSPropertyMarginLeft, attribute.value());
336 addHTMLLengthToStyle(style, CSSPropertyMarginRight, attribute.value());
337 } else if (attribute.name() == alignAttr) {
338 if (!attribute.value().isEmpty()) {
339 if (equalIgnoringCase(attribute.value(), "center")) {
antti@apple.com708a2782012-02-21 13:49:15 +0000340 addPropertyToAttributeStyle(style, CSSPropertyWebkitMarginStart, CSSValueAuto);
341 addPropertyToAttributeStyle(style, CSSPropertyWebkitMarginEnd, CSSValueAuto);
kling@webkit.org8b0e8432012-02-11 19:29:49 +0000342 } else
kling@webkit.org260fca82012-05-16 00:34:16 +0000343 addPropertyToAttributeStyle(style, CSSPropertyFloat, attribute.value());
kling@webkit.org8b0e8432012-02-11 19:29:49 +0000344 }
kling@webkit.org260fca82012-05-16 00:34:16 +0000345 } else if (attribute.name() == rulesAttr) {
kling@webkit.org8b0e8432012-02-11 19:29:49 +0000346 // The presence of a valid rules attribute causes border collapsing to be enabled.
347 if (m_rulesAttr != UnsetRules)
antti@apple.com708a2782012-02-21 13:49:15 +0000348 addPropertyToAttributeStyle(style, CSSPropertyBorderCollapse, CSSValueCollapse);
kling@webkit.org260fca82012-05-16 00:34:16 +0000349 } else if (attribute.name() == frameAttr) {
kling@webkit.org8b0e8432012-02-11 19:29:49 +0000350 bool borderTop;
351 bool borderRight;
352 bool borderBottom;
353 bool borderLeft;
kling@webkit.org260fca82012-05-16 00:34:16 +0000354 if (getBordersFromFrameAttributeValue(attribute.value(), borderTop, borderRight, borderBottom, borderLeft)) {
kling@webkit.org14789b92012-02-23 21:15:16 +0000355 addPropertyToAttributeStyle(style, CSSPropertyBorderWidth, CSSValueThin);
antti@apple.com708a2782012-02-21 13:49:15 +0000356 addPropertyToAttributeStyle(style, CSSPropertyBorderTopStyle, borderTop ? CSSValueSolid : CSSValueHidden);
357 addPropertyToAttributeStyle(style, CSSPropertyBorderBottomStyle, borderBottom ? CSSValueSolid : CSSValueHidden);
358 addPropertyToAttributeStyle(style, CSSPropertyBorderLeftStyle, borderLeft ? CSSValueSolid : CSSValueHidden);
359 addPropertyToAttributeStyle(style, CSSPropertyBorderRightStyle, borderRight ? CSSValueSolid : CSSValueHidden);
kling@webkit.org8b0e8432012-02-11 19:29:49 +0000360 }
361 } else
kling@webkit.org260fca82012-05-16 00:34:16 +0000362 HTMLElement::collectStyleForAttribute(attribute, style);
kling@webkit.org8b0e8432012-02-11 19:29:49 +0000363}
364
kling@webkit.org44bc0dd2012-02-28 22:21:02 +0000365bool HTMLTableElement::isPresentationAttribute(const QualifiedName& name) const
kling@webkit.org11f25562012-02-13 10:36:55 +0000366{
kling@webkit.org44bc0dd2012-02-28 22:21:02 +0000367 if (name == widthAttr || name == heightAttr || name == bgcolorAttr || name == backgroundAttr || name == valignAttr || name == vspaceAttr || name == hspaceAttr || name == alignAttr || name == cellspacingAttr || name == borderAttr || name == bordercolorAttr || name == frameAttr || name == rulesAttr)
kling@webkit.org11f25562012-02-13 10:36:55 +0000368 return true;
kling@webkit.org44bc0dd2012-02-28 22:21:02 +0000369 return HTMLElement::isPresentationAttribute(name);
kling@webkit.org11f25562012-02-13 10:36:55 +0000370}
371
kling@webkit.org260fca82012-05-16 00:34:16 +0000372void HTMLTableElement::parseAttribute(const Attribute& attribute)
eseidel787da6b2006-05-12 19:44:03 +0000373{
darin@apple.com12304112008-01-04 01:17:05 +0000374 CellBorders bordersBefore = cellBorders();
hyatt@apple.comcd9e4092008-01-18 21:56:31 +0000375 unsigned short oldPadding = m_padding;
376
kling@webkit.org260fca82012-05-16 00:34:16 +0000377 if (attribute.name() == borderAttr) {
kling@webkit.org8b0e8432012-02-11 19:29:49 +0000378 // FIXME: This attribute is a mess.
hyatteef21e02006-09-17 07:57:56 +0000379 m_borderAttr = true;
kling@webkit.org260fca82012-05-16 00:34:16 +0000380 if (!attribute.isNull()) {
381 int border = attribute.isEmpty() ? 1 : attribute.value().toInt();
hyatteef21e02006-09-17 07:57:56 +0000382 m_borderAttr = border;
eseidel787da6b2006-05-12 19:44:03 +0000383 }
kling@webkit.org260fca82012-05-16 00:34:16 +0000384 } else if (attribute.name() == bordercolorAttr) {
385 m_borderColorAttr = !attribute.isEmpty();
386 } else if (attribute.name() == frameAttr) {
kling@webkit.org8b0e8432012-02-11 19:29:49 +0000387 // FIXME: This attribute is a mess.
388 bool borderTop;
389 bool borderRight;
390 bool borderBottom;
391 bool borderLeft;
kling@webkit.org260fca82012-05-16 00:34:16 +0000392 m_frameAttr = getBordersFromFrameAttributeValue(attribute.value(), borderTop, borderRight, borderBottom, borderLeft);
393 } else if (attribute.name() == rulesAttr) {
hyatteef21e02006-09-17 07:57:56 +0000394 m_rulesAttr = UnsetRules;
kling@webkit.org260fca82012-05-16 00:34:16 +0000395 if (equalIgnoringCase(attribute.value(), "none"))
hyatteef21e02006-09-17 07:57:56 +0000396 m_rulesAttr = NoneRules;
kling@webkit.org260fca82012-05-16 00:34:16 +0000397 else if (equalIgnoringCase(attribute.value(), "groups"))
hyatteef21e02006-09-17 07:57:56 +0000398 m_rulesAttr = GroupsRules;
kling@webkit.org260fca82012-05-16 00:34:16 +0000399 else if (equalIgnoringCase(attribute.value(), "rows"))
hyatteef21e02006-09-17 07:57:56 +0000400 m_rulesAttr = RowsRules;
kling@webkit.org260fca82012-05-16 00:34:16 +0000401 if (equalIgnoringCase(attribute.value(), "cols"))
hyatteef21e02006-09-17 07:57:56 +0000402 m_rulesAttr = ColsRules;
kling@webkit.org260fca82012-05-16 00:34:16 +0000403 if (equalIgnoringCase(attribute.value(), "all"))
hyatteef21e02006-09-17 07:57:56 +0000404 m_rulesAttr = AllRules;
kling@webkit.org260fca82012-05-16 00:34:16 +0000405 } else if (attribute.name() == cellpaddingAttr) {
406 if (!attribute.value().isEmpty())
407 m_padding = max(0, attribute.value().toInt());
eseidel787da6b2006-05-12 19:44:03 +0000408 else
hyatteef21e02006-09-17 07:57:56 +0000409 m_padding = 1;
kling@webkit.org260fca82012-05-16 00:34:16 +0000410 } else if (attribute.name() == colsAttr) {
eseidel787da6b2006-05-12 19:44:03 +0000411 // ###
eseidel787da6b2006-05-12 19:44:03 +0000412 } else
kling@webkit.org260fca82012-05-16 00:34:16 +0000413 HTMLElement::parseAttribute(attribute);
darin@apple.com12304112008-01-04 01:17:05 +0000414
hyatt@apple.comcd9e4092008-01-18 21:56:31 +0000415 if (bordersBefore != cellBorders() || oldPadding != m_padding) {
kling@webkit.org854221b2012-01-26 19:02:27 +0000416 m_sharedCellStyle = 0;
darin@apple.com12304112008-01-04 01:17:05 +0000417 bool cellChanged = false;
418 for (Node* child = firstChild(); child; child = child->nextSibling())
419 cellChanged |= setTableCellsChanged(child);
420 if (cellChanged)
hyatt@apple.comf6d72f32009-04-10 00:05:02 +0000421 setNeedsStyleRecalc();
darin@apple.com12304112008-01-04 01:17:05 +0000422 }
eseidel787da6b2006-05-12 19:44:03 +0000423}
424
antti@apple.come89e04d2012-02-03 19:46:48 +0000425static StylePropertySet* leakBorderStyle(int value)
kling@webkit.org854221b2012-01-26 19:02:27 +0000426{
antti@apple.come89e04d2012-02-03 19:46:48 +0000427 RefPtr<StylePropertySet> style = StylePropertySet::create();
kling@webkit.org854221b2012-01-26 19:02:27 +0000428 style->setProperty(CSSPropertyBorderTopStyle, value);
429 style->setProperty(CSSPropertyBorderBottomStyle, value);
430 style->setProperty(CSSPropertyBorderLeftStyle, value);
431 style->setProperty(CSSPropertyBorderRightStyle, value);
432 return style.release().leakRef();
433}
434
kling@webkit.org513d26f2012-08-06 13:14:04 +0000435const StylePropertySet* HTMLTableElement::additionalAttributeStyle()
eseidel787da6b2006-05-12 19:44:03 +0000436{
robert@webkit.orgceeb5dc2012-04-24 19:03:44 +0000437 if (m_frameAttr)
kling@webkit.org854221b2012-01-26 19:02:27 +0000438 return 0;
robert@webkit.orgceeb5dc2012-04-24 19:03:44 +0000439
440 if (!m_borderAttr && !m_borderColorAttr) {
441 // Setting the border to 'hidden' allows it to win over any border
442 // set on the table's cells during border-conflict resolution.
443 if (m_rulesAttr != UnsetRules) {
444 static StylePropertySet* solidBorderStyle = leakBorderStyle(CSSValueHidden);
445 return solidBorderStyle;
446 }
447 return 0;
448 }
darin@apple.com48ac3c42008-06-14 08:46:51 +0000449
kling@webkit.org854221b2012-01-26 19:02:27 +0000450 if (m_borderColorAttr) {
antti@apple.come89e04d2012-02-03 19:46:48 +0000451 static StylePropertySet* solidBorderStyle = leakBorderStyle(CSSValueSolid);
kling@webkit.org854221b2012-01-26 19:02:27 +0000452 return solidBorderStyle;
eseidel787da6b2006-05-12 19:44:03 +0000453 }
antti@apple.come89e04d2012-02-03 19:46:48 +0000454 static StylePropertySet* outsetBorderStyle = leakBorderStyle(CSSValueOutset);
kling@webkit.org854221b2012-01-26 19:02:27 +0000455 return outsetBorderStyle;
eseidel787da6b2006-05-12 19:44:03 +0000456}
457
darin@apple.com12304112008-01-04 01:17:05 +0000458HTMLTableElement::CellBorders HTMLTableElement::cellBorders() const
459{
460 switch (m_rulesAttr) {
461 case NoneRules:
462 case GroupsRules:
463 return NoBorders;
464 case AllRules:
465 return SolidBorders;
466 case ColsRules:
467 return SolidBordersColsOnly;
468 case RowsRules:
469 return SolidBordersRowsOnly;
470 case UnsetRules:
471 if (!m_borderAttr)
472 return NoBorders;
473 if (m_borderColorAttr)
474 return SolidBorders;
475 return InsetBorders;
476 }
477 ASSERT_NOT_REACHED();
478 return NoBorders;
479}
480
antti@apple.come89e04d2012-02-03 19:46:48 +0000481PassRefPtr<StylePropertySet> HTMLTableElement::createSharedCellStyle()
hyatt@apple.comcd9e4092008-01-18 21:56:31 +0000482{
antti@apple.come89e04d2012-02-03 19:46:48 +0000483 RefPtr<StylePropertySet> style = StylePropertySet::create();
hyatt@apple.comcd9e4092008-01-18 21:56:31 +0000484
kling@webkit.org854221b2012-01-26 19:02:27 +0000485 switch (cellBorders()) {
486 case SolidBordersColsOnly:
487 style->setProperty(CSSPropertyBorderLeftWidth, CSSValueThin);
488 style->setProperty(CSSPropertyBorderRightWidth, CSSValueThin);
489 style->setProperty(CSSPropertyBorderLeftStyle, CSSValueSolid);
490 style->setProperty(CSSPropertyBorderRightStyle, CSSValueSolid);
kling@webkit.orgb01b7972012-04-10 00:44:20 +0000491 style->setProperty(CSSPropertyBorderColor, cssValuePool().createInheritedValue());
kling@webkit.org854221b2012-01-26 19:02:27 +0000492 break;
493 case SolidBordersRowsOnly:
494 style->setProperty(CSSPropertyBorderTopWidth, CSSValueThin);
495 style->setProperty(CSSPropertyBorderBottomWidth, CSSValueThin);
496 style->setProperty(CSSPropertyBorderTopStyle, CSSValueSolid);
497 style->setProperty(CSSPropertyBorderBottomStyle, CSSValueSolid);
kling@webkit.orgb01b7972012-04-10 00:44:20 +0000498 style->setProperty(CSSPropertyBorderColor, cssValuePool().createInheritedValue());
kling@webkit.org854221b2012-01-26 19:02:27 +0000499 break;
500 case SolidBorders:
kling@webkit.orgb01b7972012-04-10 00:44:20 +0000501 style->setProperty(CSSPropertyBorderWidth, cssValuePool().createValue(1, CSSPrimitiveValue::CSS_PX));
502 style->setProperty(CSSPropertyBorderStyle, cssValuePool().createIdentifierValue(CSSValueSolid));
503 style->setProperty(CSSPropertyBorderColor, cssValuePool().createInheritedValue());
kling@webkit.org854221b2012-01-26 19:02:27 +0000504 break;
505 case InsetBorders:
kling@webkit.orgb01b7972012-04-10 00:44:20 +0000506 style->setProperty(CSSPropertyBorderWidth, cssValuePool().createValue(1, CSSPrimitiveValue::CSS_PX));
507 style->setProperty(CSSPropertyBorderStyle, cssValuePool().createIdentifierValue(CSSValueInset));
508 style->setProperty(CSSPropertyBorderColor, cssValuePool().createInheritedValue());
kling@webkit.org854221b2012-01-26 19:02:27 +0000509 break;
510 case NoBorders:
robert@webkit.orgf911cc32012-08-25 16:20:23 +0000511 // If 'rules=none' then allow any borders set at cell level to take effect.
kling@webkit.org854221b2012-01-26 19:02:27 +0000512 break;
eseidel787da6b2006-05-12 19:44:03 +0000513 }
kling@webkit.orge72793e2011-12-24 21:24:59 +0000514
kling@webkit.org2340d5e2012-02-25 17:43:32 +0000515 if (m_padding)
kling@webkit.orgb01b7972012-04-10 00:44:20 +0000516 style->setProperty(CSSPropertyPadding, cssValuePool().createValue(m_padding, CSSPrimitiveValue::CSS_PX));
kling@webkit.orge72793e2011-12-24 21:24:59 +0000517
kling@webkit.org854221b2012-01-26 19:02:27 +0000518 return style.release();
hyatt@apple.comcd9e4092008-01-18 21:56:31 +0000519}
520
kling@webkit.org513d26f2012-08-06 13:14:04 +0000521const StylePropertySet* HTMLTableElement::additionalCellStyle()
kling@webkit.org854221b2012-01-26 19:02:27 +0000522{
523 if (!m_sharedCellStyle)
524 m_sharedCellStyle = createSharedCellStyle();
kling@webkit.orgdc26b372012-02-09 07:14:55 +0000525 return m_sharedCellStyle.get();
kling@webkit.org854221b2012-01-26 19:02:27 +0000526}
527
antti@apple.come89e04d2012-02-03 19:46:48 +0000528static StylePropertySet* leakGroupBorderStyle(int rows)
kling@webkit.org854221b2012-01-26 19:02:27 +0000529{
antti@apple.come89e04d2012-02-03 19:46:48 +0000530 RefPtr<StylePropertySet> style = StylePropertySet::create();
kling@webkit.org854221b2012-01-26 19:02:27 +0000531 if (rows) {
532 style->setProperty(CSSPropertyBorderTopWidth, CSSValueThin);
533 style->setProperty(CSSPropertyBorderBottomWidth, CSSValueThin);
534 style->setProperty(CSSPropertyBorderTopStyle, CSSValueSolid);
535 style->setProperty(CSSPropertyBorderBottomStyle, CSSValueSolid);
536 } else {
537 style->setProperty(CSSPropertyBorderLeftWidth, CSSValueThin);
538 style->setProperty(CSSPropertyBorderRightWidth, CSSValueThin);
539 style->setProperty(CSSPropertyBorderLeftStyle, CSSValueSolid);
540 style->setProperty(CSSPropertyBorderRightStyle, CSSValueSolid);
541 }
542 return style.release().leakRef();
543}
544
kling@webkit.org513d26f2012-08-06 13:14:04 +0000545const StylePropertySet* HTMLTableElement::additionalGroupStyle(bool rows)
hyatteef21e02006-09-17 07:57:56 +0000546{
547 if (m_rulesAttr != GroupsRules)
kling@webkit.org854221b2012-01-26 19:02:27 +0000548 return 0;
hyatteef21e02006-09-17 07:57:56 +0000549
kling@webkit.org854221b2012-01-26 19:02:27 +0000550 if (rows) {
antti@apple.come89e04d2012-02-03 19:46:48 +0000551 static StylePropertySet* rowBorderStyle = leakGroupBorderStyle(true);
kling@webkit.org854221b2012-01-26 19:02:27 +0000552 return rowBorderStyle;
hyatteef21e02006-09-17 07:57:56 +0000553 }
antti@apple.come89e04d2012-02-03 19:46:48 +0000554 static StylePropertySet* columnBorderStyle = leakGroupBorderStyle(false);
kling@webkit.org854221b2012-01-26 19:02:27 +0000555 return columnBorderStyle;
hyatteef21e02006-09-17 07:57:56 +0000556}
557
kling@webkit.orgd8a6d152012-05-08 16:27:04 +0000558bool HTMLTableElement::isURLAttribute(const Attribute& attribute) const
eseidel787da6b2006-05-12 19:44:03 +0000559{
kling@webkit.orgd8a6d152012-05-08 16:27:04 +0000560 return attribute.name() == backgroundAttr || HTMLElement::isURLAttribute(attribute);
eseidel787da6b2006-05-12 19:44:03 +0000561}
562
rniwa@webkit.org4823cc12012-07-09 17:40:09 +0000563PassRefPtr<HTMLCollection> HTMLTableElement::rows()
eseidel787da6b2006-05-12 19:44:03 +0000564{
rniwa@webkit.org28acc312012-06-29 23:56:42 +0000565 return ensureCachedHTMLCollection(TableRows);
eseidel787da6b2006-05-12 19:44:03 +0000566}
567
rniwa@webkit.org4823cc12012-07-09 17:40:09 +0000568PassRefPtr<HTMLCollection> HTMLTableElement::tBodies()
eseidel787da6b2006-05-12 19:44:03 +0000569{
kling@webkit.orga3a65e32012-01-01 21:05:42 +0000570 return ensureCachedHTMLCollection(TableTBodies);
eseidel787da6b2006-05-12 19:44:03 +0000571}
572
eseidel787da6b2006-05-12 19:44:03 +0000573String HTMLTableElement::rules() const
574{
commit-queue@webkit.org03477c82011-09-02 17:07:51 +0000575 return getAttribute(rulesAttr);
eseidel787da6b2006-05-12 19:44:03 +0000576}
577
eseidel787da6b2006-05-12 19:44:03 +0000578String HTMLTableElement::summary() const
579{
commit-queue@webkit.org03477c82011-09-02 17:07:51 +0000580 return getAttribute(summaryAttr);
eseidel787da6b2006-05-12 19:44:03 +0000581}
582
commit-queue@webkit.orgbd9bc9a2012-05-30 20:50:31 +0000583void HTMLTableElement::addSubresourceAttributeURLs(ListHashSet<KURL>& urls) const
beidson@apple.coma4fb38f2008-03-27 04:08:17 +0000584{
commit-queue@webkit.orgbd9bc9a2012-05-30 20:50:31 +0000585 HTMLElement::addSubresourceAttributeURLs(urls);
ddkilzer@apple.come9a55042008-12-23 00:00:14 +0000586
commit-queue@webkit.org03477c82011-09-02 17:07:51 +0000587 addSubresourceURL(urls, document()->completeURL(getAttribute(backgroundAttr)));
beidson@apple.coma4fb38f2008-03-27 04:08:17 +0000588}
589
eseidel787da6b2006-05-12 19:44:03 +0000590}