Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / html / HTMLTableElement.cpp
1 /*
2  * 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)
7  * Copyright (C) 2003, 2004, 2005, 2006, 2008, 2010, 2011 Apple Inc. All rights reserved.
8  *
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
21  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22  * Boston, MA 02110-1301, USA.
23  */
24
25 #include "config.h"
26 #include "core/html/HTMLTableElement.h"
27
28 #include "CSSPropertyNames.h"
29 #include "CSSValueKeywords.h"
30 #include "HTMLNames.h"
31 #include "bindings/v8/ExceptionState.h"
32 #include "bindings/v8/ExceptionStatePlaceholder.h"
33 #include "core/css/CSSImageValue.h"
34 #include "core/css/CSSValuePool.h"
35 #include "core/css/StylePropertySet.h"
36 #include "core/dom/Attribute.h"
37 #include "core/dom/ElementTraversal.h"
38 #include "core/dom/ExceptionCode.h"
39 #include "core/frame/UseCounter.h"
40 #include "core/html/HTMLTableCaptionElement.h"
41 #include "core/html/HTMLTableCellElement.h"
42 #include "core/html/HTMLTableRowElement.h"
43 #include "core/html/HTMLTableRowsCollection.h"
44 #include "core/html/HTMLTableSectionElement.h"
45 #include "core/html/parser/HTMLParserIdioms.h"
46 #include "core/rendering/RenderTable.h"
47 #include "wtf/StdLibExtras.h"
48
49 namespace WebCore {
50
51 using namespace HTMLNames;
52
53 HTMLTableElement::HTMLTableElement(Document& document)
54     : HTMLElement(tableTag, document)
55     , m_borderAttr(false)
56     , m_borderColorAttr(false)
57     , m_frameAttr(false)
58     , m_rulesAttr(UnsetRules)
59     , m_padding(1)
60 {
61     ScriptWrappable::init(this);
62 }
63
64 PassRefPtrWillBeRawPtr<HTMLTableElement> HTMLTableElement::create(Document& document)
65 {
66     return adoptRefWillBeRefCountedGarbageCollected(new HTMLTableElement(document));
67 }
68
69 HTMLTableCaptionElement* HTMLTableElement::caption() const
70 {
71     return Traversal<HTMLTableCaptionElement>::firstChild(*this);
72 }
73
74 void HTMLTableElement::setCaption(PassRefPtrWillBeRawPtr<HTMLTableCaptionElement> newCaption, ExceptionState& exceptionState)
75 {
76     deleteCaption();
77     insertBefore(newCaption, firstChild(), exceptionState);
78 }
79
80 HTMLTableSectionElement* HTMLTableElement::tHead() const
81 {
82     for (Element* child = ElementTraversal::firstWithin(*this); child; child = ElementTraversal::nextSibling(*child)) {
83         if (child->hasTagName(theadTag))
84             return toHTMLTableSectionElement(child);
85     }
86     return 0;
87 }
88
89 void HTMLTableElement::setTHead(PassRefPtrWillBeRawPtr<HTMLTableSectionElement> newHead, ExceptionState& exceptionState)
90 {
91     deleteTHead();
92
93     Element* child;
94     for (child = ElementTraversal::firstWithin(*this); child; child = ElementTraversal::nextSibling(*child)) {
95         if (!child->hasTagName(captionTag) && !child->hasTagName(colgroupTag))
96             break;
97     }
98
99     insertBefore(newHead, child, exceptionState);
100 }
101
102 HTMLTableSectionElement* HTMLTableElement::tFoot() const
103 {
104     for (Element* child = ElementTraversal::firstWithin(*this); child; child = ElementTraversal::nextSibling(*child)) {
105         if (child->hasTagName(tfootTag))
106             return toHTMLTableSectionElement(child);
107     }
108     return 0;
109 }
110
111 void HTMLTableElement::setTFoot(PassRefPtrWillBeRawPtr<HTMLTableSectionElement> newFoot, ExceptionState& exceptionState)
112 {
113     deleteTFoot();
114
115     Element* child;
116     for (child = ElementTraversal::firstWithin(*this); child; child = ElementTraversal::nextSibling(*child)) {
117         if (!child->hasTagName(captionTag) && !child->hasTagName(colgroupTag) && !child->hasTagName(theadTag))
118             break;
119     }
120
121     insertBefore(newFoot, child, exceptionState);
122 }
123
124 PassRefPtrWillBeRawPtr<HTMLElement> HTMLTableElement::createTHead()
125 {
126     if (HTMLTableSectionElement* existingHead = tHead())
127         return existingHead;
128     RefPtrWillBeRawPtr<HTMLTableSectionElement> head = HTMLTableSectionElement::create(theadTag, document());
129     setTHead(head, IGNORE_EXCEPTION);
130     return head.release();
131 }
132
133 void HTMLTableElement::deleteTHead()
134 {
135     removeChild(tHead(), IGNORE_EXCEPTION);
136 }
137
138 PassRefPtrWillBeRawPtr<HTMLElement> HTMLTableElement::createTFoot()
139 {
140     if (HTMLTableSectionElement* existingFoot = tFoot())
141         return existingFoot;
142     RefPtrWillBeRawPtr<HTMLTableSectionElement> foot = HTMLTableSectionElement::create(tfootTag, document());
143     setTFoot(foot, IGNORE_EXCEPTION);
144     return foot.release();
145 }
146
147 void HTMLTableElement::deleteTFoot()
148 {
149     removeChild(tFoot(), IGNORE_EXCEPTION);
150 }
151
152 PassRefPtrWillBeRawPtr<HTMLElement> HTMLTableElement::createTBody()
153 {
154     RefPtrWillBeRawPtr<HTMLTableSectionElement> body = HTMLTableSectionElement::create(tbodyTag, document());
155     Node* referenceElement = lastBody() ? lastBody()->nextSibling() : 0;
156
157     insertBefore(body, referenceElement);
158     return body.release();
159 }
160
161 PassRefPtrWillBeRawPtr<HTMLElement> HTMLTableElement::createCaption()
162 {
163     if (HTMLTableCaptionElement* existingCaption = caption())
164         return existingCaption;
165     RefPtrWillBeRawPtr<HTMLTableCaptionElement> caption = HTMLTableCaptionElement::create(document());
166     setCaption(caption, IGNORE_EXCEPTION);
167     return caption.release();
168 }
169
170 void HTMLTableElement::deleteCaption()
171 {
172     removeChild(caption(), IGNORE_EXCEPTION);
173 }
174
175 HTMLTableSectionElement* HTMLTableElement::lastBody() const
176 {
177     for (Node* child = lastChild(); child; child = child->previousSibling()) {
178         if (child->hasTagName(tbodyTag))
179             return toHTMLTableSectionElement(child);
180     }
181     return 0;
182 }
183
184 PassRefPtrWillBeRawPtr<HTMLElement> HTMLTableElement::insertRow(ExceptionState& exceptionState)
185 {
186     // The default 'index' argument value is -1.
187     return insertRow(-1, exceptionState);
188 }
189
190 PassRefPtrWillBeRawPtr<HTMLElement> HTMLTableElement::insertRow(int index, ExceptionState& exceptionState)
191 {
192     if (index < -1) {
193         exceptionState.throwDOMException(IndexSizeError, "The index provided (" + String::number(index) + ") is less than -1.");
194         return nullptr;
195     }
196
197     RefPtrWillBeRawPtr<Node> protectFromMutationEvents(this);
198
199     RefPtrWillBeRawPtr<HTMLTableRowElement> lastRow = nullptr;
200     RefPtrWillBeRawPtr<HTMLTableRowElement> row = nullptr;
201     if (index == -1)
202         lastRow = HTMLTableRowsCollection::lastRow(*this);
203     else {
204         for (int i = 0; i <= index; ++i) {
205             row = HTMLTableRowsCollection::rowAfter(*this, lastRow.get());
206             if (!row) {
207                 if (i != index) {
208                     exceptionState.throwDOMException(IndexSizeError, "The index provided (" + String::number(index) + ") is greater than the number of rows in the table (" + String::number(i) + ").");
209                     return nullptr;
210                 }
211                 break;
212             }
213             lastRow = row;
214         }
215     }
216
217     RefPtr<ContainerNode> parent;
218     if (lastRow)
219         parent = row ? row->parentNode() : lastRow->parentNode();
220     else {
221         parent = lastBody();
222         if (!parent) {
223             RefPtrWillBeRawPtr<HTMLTableSectionElement> newBody = HTMLTableSectionElement::create(tbodyTag, document());
224             RefPtrWillBeRawPtr<HTMLTableRowElement> newRow = HTMLTableRowElement::create(document());
225             newBody->appendChild(newRow, exceptionState);
226             appendChild(newBody.release(), exceptionState);
227             return newRow.release();
228         }
229     }
230
231     RefPtrWillBeRawPtr<HTMLTableRowElement> newRow = HTMLTableRowElement::create(document());
232     parent->insertBefore(newRow, row.get(), exceptionState);
233     return newRow.release();
234 }
235
236 void HTMLTableElement::deleteRow(int index, ExceptionState& exceptionState)
237 {
238     if (index < -1) {
239         exceptionState.throwDOMException(IndexSizeError, "The index provided (" + String::number(index) + ") is less than -1.");
240         return;
241     }
242
243     HTMLTableRowElement* row = 0;
244     int i = 0;
245     if (index == -1)
246         row = HTMLTableRowsCollection::lastRow(*this);
247     else {
248         for (i = 0; i <= index; ++i) {
249             row = HTMLTableRowsCollection::rowAfter(*this, row);
250             if (!row)
251                 break;
252         }
253     }
254     if (!row) {
255         exceptionState.throwDOMException(IndexSizeError, "The index provided (" + String::number(index) + ") is greater than the number of rows in the table (" + String::number(i) + ").");
256         return;
257     }
258     row->remove(exceptionState);
259 }
260
261 void HTMLTableElement::setNeedsTableStyleRecalc() const
262 {
263     Element* element = ElementTraversal::next(*this, this);
264     while (element) {
265         element->setNeedsStyleRecalc(LocalStyleChange);
266         if (isHTMLTableCellElement(*element))
267             element = ElementTraversal::nextSkippingChildren(*element, this);
268         else
269             element = ElementTraversal::next(*element, this);
270     }
271 }
272
273 static bool getBordersFromFrameAttributeValue(const AtomicString& value, bool& borderTop, bool& borderRight, bool& borderBottom, bool& borderLeft)
274 {
275     borderTop = false;
276     borderRight = false;
277     borderBottom = false;
278     borderLeft = false;
279
280     if (equalIgnoringCase(value, "above"))
281         borderTop = true;
282     else if (equalIgnoringCase(value, "below"))
283         borderBottom = true;
284     else if (equalIgnoringCase(value, "hsides"))
285         borderTop = borderBottom = true;
286     else if (equalIgnoringCase(value, "vsides"))
287         borderLeft = borderRight = true;
288     else if (equalIgnoringCase(value, "lhs"))
289         borderLeft = true;
290     else if (equalIgnoringCase(value, "rhs"))
291         borderRight = true;
292     else if (equalIgnoringCase(value, "box") || equalIgnoringCase(value, "border"))
293         borderTop = borderBottom = borderLeft = borderRight = true;
294     else if (!equalIgnoringCase(value, "void"))
295         return false;
296     return true;
297 }
298
299 void HTMLTableElement::collectStyleForPresentationAttribute(const QualifiedName& name, const AtomicString& value, MutableStylePropertySet* style)
300 {
301     if (name == widthAttr)
302         addHTMLLengthToStyle(style, CSSPropertyWidth, value);
303     else if (name == heightAttr)
304         addHTMLLengthToStyle(style, CSSPropertyHeight, value);
305     else if (name == borderAttr)
306         addPropertyToPresentationAttributeStyle(style, CSSPropertyBorderWidth, parseBorderWidthAttribute(value), CSSPrimitiveValue::CSS_PX);
307     else if (name == bordercolorAttr) {
308         if (!value.isEmpty())
309             addHTMLColorToStyle(style, CSSPropertyBorderColor, value);
310     } else if (name == bgcolorAttr)
311         addHTMLColorToStyle(style, CSSPropertyBackgroundColor, value);
312     else if (name == backgroundAttr) {
313         String url = stripLeadingAndTrailingHTMLSpaces(value);
314         if (!url.isEmpty()) {
315             RefPtrWillBeRawPtr<CSSImageValue> imageValue = CSSImageValue::create(url, document().completeURL(url));
316             imageValue->setReferrer(document().outgoingReferrer());
317             style->setProperty(CSSProperty(CSSPropertyBackgroundImage, imageValue.release()));
318         }
319     } else if (name == valignAttr) {
320         if (!value.isEmpty())
321             addPropertyToPresentationAttributeStyle(style, CSSPropertyVerticalAlign, value);
322     } else if (name == cellspacingAttr) {
323         if (!value.isEmpty())
324             addHTMLLengthToStyle(style, CSSPropertyBorderSpacing, value);
325     } else if (name == vspaceAttr) {
326         UseCounter::count(document(), UseCounter::HTMLTableElementVspace);
327         addHTMLLengthToStyle(style, CSSPropertyMarginTop, value);
328         addHTMLLengthToStyle(style, CSSPropertyMarginBottom, value);
329     } else if (name == hspaceAttr) {
330         UseCounter::count(document(), UseCounter::HTMLTableElementHspace);
331         addHTMLLengthToStyle(style, CSSPropertyMarginLeft, value);
332         addHTMLLengthToStyle(style, CSSPropertyMarginRight, value);
333     } else if (name == alignAttr) {
334         if (!value.isEmpty()) {
335             if (equalIgnoringCase(value, "center")) {
336                 addPropertyToPresentationAttributeStyle(style, CSSPropertyWebkitMarginStart, CSSValueAuto);
337                 addPropertyToPresentationAttributeStyle(style, CSSPropertyWebkitMarginEnd, CSSValueAuto);
338             } else
339                 addPropertyToPresentationAttributeStyle(style, CSSPropertyFloat, value);
340         }
341     } else if (name == rulesAttr) {
342         // The presence of a valid rules attribute causes border collapsing to be enabled.
343         if (m_rulesAttr != UnsetRules)
344             addPropertyToPresentationAttributeStyle(style, CSSPropertyBorderCollapse, CSSValueCollapse);
345     } else if (name == frameAttr) {
346         bool borderTop;
347         bool borderRight;
348         bool borderBottom;
349         bool borderLeft;
350         if (getBordersFromFrameAttributeValue(value, borderTop, borderRight, borderBottom, borderLeft)) {
351             addPropertyToPresentationAttributeStyle(style, CSSPropertyBorderWidth, CSSValueThin);
352             addPropertyToPresentationAttributeStyle(style, CSSPropertyBorderTopStyle, borderTop ? CSSValueSolid : CSSValueHidden);
353             addPropertyToPresentationAttributeStyle(style, CSSPropertyBorderBottomStyle, borderBottom ? CSSValueSolid : CSSValueHidden);
354             addPropertyToPresentationAttributeStyle(style, CSSPropertyBorderLeftStyle, borderLeft ? CSSValueSolid : CSSValueHidden);
355             addPropertyToPresentationAttributeStyle(style, CSSPropertyBorderRightStyle, borderRight ? CSSValueSolid : CSSValueHidden);
356         }
357     } else
358         HTMLElement::collectStyleForPresentationAttribute(name, value, style);
359 }
360
361 bool HTMLTableElement::isPresentationAttribute(const QualifiedName& name) const
362 {
363     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)
364         return true;
365     return HTMLElement::isPresentationAttribute(name);
366 }
367
368 void HTMLTableElement::parseAttribute(const QualifiedName& name, const AtomicString& value)
369 {
370     CellBorders bordersBefore = cellBorders();
371     unsigned short oldPadding = m_padding;
372
373     if (name == borderAttr)  {
374         // FIXME: This attribute is a mess.
375         m_borderAttr = parseBorderWidthAttribute(value);
376     } else if (name == bordercolorAttr) {
377         m_borderColorAttr = !value.isEmpty();
378     } else if (name == frameAttr) {
379         // FIXME: This attribute is a mess.
380         bool borderTop;
381         bool borderRight;
382         bool borderBottom;
383         bool borderLeft;
384         m_frameAttr = getBordersFromFrameAttributeValue(value, borderTop, borderRight, borderBottom, borderLeft);
385     } else if (name == rulesAttr) {
386         m_rulesAttr = UnsetRules;
387         if (equalIgnoringCase(value, "none"))
388             m_rulesAttr = NoneRules;
389         else if (equalIgnoringCase(value, "groups"))
390             m_rulesAttr = GroupsRules;
391         else if (equalIgnoringCase(value, "rows"))
392             m_rulesAttr = RowsRules;
393         else if (equalIgnoringCase(value, "cols"))
394             m_rulesAttr = ColsRules;
395         else if (equalIgnoringCase(value, "all"))
396             m_rulesAttr = AllRules;
397     } else if (name == cellpaddingAttr) {
398         if (!value.isEmpty())
399             m_padding = max(0, value.toInt());
400         else
401             m_padding = 1;
402     } else if (name == colsAttr) {
403         // ###
404     } else
405         HTMLElement::parseAttribute(name, value);
406
407     if (bordersBefore != cellBorders() || oldPadding != m_padding) {
408         m_sharedCellStyle = nullptr;
409         setNeedsTableStyleRecalc();
410     }
411 }
412
413 static PassRefPtr<StylePropertySet> createBorderStyle(CSSValueID value)
414 {
415     RefPtrWillBeRawPtr<MutableStylePropertySet> style = MutableStylePropertySet::create();
416     style->setProperty(CSSPropertyBorderTopStyle, value);
417     style->setProperty(CSSPropertyBorderBottomStyle, value);
418     style->setProperty(CSSPropertyBorderLeftStyle, value);
419     style->setProperty(CSSPropertyBorderRightStyle, value);
420     return style.release();
421 }
422
423 const StylePropertySet* HTMLTableElement::additionalPresentationAttributeStyle()
424 {
425     if (m_frameAttr)
426         return 0;
427
428     if (!m_borderAttr && !m_borderColorAttr) {
429         // Setting the border to 'hidden' allows it to win over any border
430         // set on the table's cells during border-conflict resolution.
431         if (m_rulesAttr != UnsetRules) {
432             DEFINE_STATIC_REF(StylePropertySet, solidBorderStyle, (createBorderStyle(CSSValueHidden)));
433             return solidBorderStyle;
434         }
435         return 0;
436     }
437
438     if (m_borderColorAttr) {
439         DEFINE_STATIC_REF(StylePropertySet, solidBorderStyle, (createBorderStyle(CSSValueSolid)));
440         return solidBorderStyle;
441     }
442     DEFINE_STATIC_REF(StylePropertySet, outsetBorderStyle, (createBorderStyle(CSSValueOutset)));
443     return outsetBorderStyle;
444 }
445
446 HTMLTableElement::CellBorders HTMLTableElement::cellBorders() const
447 {
448     switch (m_rulesAttr) {
449         case NoneRules:
450         case GroupsRules:
451             return NoBorders;
452         case AllRules:
453             return SolidBorders;
454         case ColsRules:
455             return SolidBordersColsOnly;
456         case RowsRules:
457             return SolidBordersRowsOnly;
458         case UnsetRules:
459             if (!m_borderAttr)
460                 return NoBorders;
461             if (m_borderColorAttr)
462                 return SolidBorders;
463             return InsetBorders;
464     }
465     ASSERT_NOT_REACHED();
466     return NoBorders;
467 }
468
469 PassRefPtrWillBeRawPtr<StylePropertySet> HTMLTableElement::createSharedCellStyle()
470 {
471     RefPtrWillBeRawPtr<MutableStylePropertySet> style = MutableStylePropertySet::create();
472
473     switch (cellBorders()) {
474     case SolidBordersColsOnly:
475         style->setProperty(CSSPropertyBorderLeftWidth, CSSValueThin);
476         style->setProperty(CSSPropertyBorderRightWidth, CSSValueThin);
477         style->setProperty(CSSPropertyBorderLeftStyle, CSSValueSolid);
478         style->setProperty(CSSPropertyBorderRightStyle, CSSValueSolid);
479         style->setProperty(CSSPropertyBorderColor, cssValuePool().createInheritedValue());
480         break;
481     case SolidBordersRowsOnly:
482         style->setProperty(CSSPropertyBorderTopWidth, CSSValueThin);
483         style->setProperty(CSSPropertyBorderBottomWidth, CSSValueThin);
484         style->setProperty(CSSPropertyBorderTopStyle, CSSValueSolid);
485         style->setProperty(CSSPropertyBorderBottomStyle, CSSValueSolid);
486         style->setProperty(CSSPropertyBorderColor, cssValuePool().createInheritedValue());
487         break;
488     case SolidBorders:
489         style->setProperty(CSSPropertyBorderWidth, cssValuePool().createValue(1, CSSPrimitiveValue::CSS_PX));
490         style->setProperty(CSSPropertyBorderStyle, cssValuePool().createIdentifierValue(CSSValueSolid));
491         style->setProperty(CSSPropertyBorderColor, cssValuePool().createInheritedValue());
492         break;
493     case InsetBorders:
494         style->setProperty(CSSPropertyBorderWidth, cssValuePool().createValue(1, CSSPrimitiveValue::CSS_PX));
495         style->setProperty(CSSPropertyBorderStyle, cssValuePool().createIdentifierValue(CSSValueInset));
496         style->setProperty(CSSPropertyBorderColor, cssValuePool().createInheritedValue());
497         break;
498     case NoBorders:
499         // If 'rules=none' then allow any borders set at cell level to take effect.
500         break;
501     }
502
503     if (m_padding)
504         style->setProperty(CSSPropertyPadding, cssValuePool().createValue(m_padding, CSSPrimitiveValue::CSS_PX));
505
506     return style.release();
507 }
508
509 const StylePropertySet* HTMLTableElement::additionalCellStyle()
510 {
511     if (!m_sharedCellStyle)
512         m_sharedCellStyle = createSharedCellStyle();
513     return m_sharedCellStyle.get();
514 }
515
516 static PassRefPtrWillBeRawPtr<StylePropertySet> createGroupBorderStyle(int rows)
517 {
518     RefPtrWillBeRawPtr<MutableStylePropertySet> style = MutableStylePropertySet::create();
519     if (rows) {
520         style->setProperty(CSSPropertyBorderTopWidth, CSSValueThin);
521         style->setProperty(CSSPropertyBorderBottomWidth, CSSValueThin);
522         style->setProperty(CSSPropertyBorderTopStyle, CSSValueSolid);
523         style->setProperty(CSSPropertyBorderBottomStyle, CSSValueSolid);
524     } else {
525         style->setProperty(CSSPropertyBorderLeftWidth, CSSValueThin);
526         style->setProperty(CSSPropertyBorderRightWidth, CSSValueThin);
527         style->setProperty(CSSPropertyBorderLeftStyle, CSSValueSolid);
528         style->setProperty(CSSPropertyBorderRightStyle, CSSValueSolid);
529     }
530     return style.release();
531 }
532
533 const StylePropertySet* HTMLTableElement::additionalGroupStyle(bool rows)
534 {
535     if (m_rulesAttr != GroupsRules)
536         return 0;
537
538     if (rows) {
539         DEFINE_STATIC_REF(StylePropertySet, rowBorderStyle, (createGroupBorderStyle(true)));
540         return rowBorderStyle;
541     }
542     DEFINE_STATIC_REF(StylePropertySet, columnBorderStyle, (createGroupBorderStyle(false)));
543     return columnBorderStyle;
544 }
545
546 bool HTMLTableElement::isURLAttribute(const Attribute& attribute) const
547 {
548     return attribute.name() == backgroundAttr || HTMLElement::isURLAttribute(attribute);
549 }
550
551 bool HTMLTableElement::hasLegalLinkAttribute(const QualifiedName& name) const
552 {
553     return name == backgroundAttr || HTMLElement::hasLegalLinkAttribute(name);
554 }
555
556 const QualifiedName& HTMLTableElement::subResourceAttributeName() const
557 {
558     return backgroundAttr;
559 }
560
561 PassRefPtr<HTMLCollection> HTMLTableElement::rows()
562 {
563     return ensureCachedHTMLCollection(TableRows);
564 }
565
566 PassRefPtr<HTMLCollection> HTMLTableElement::tBodies()
567 {
568     return ensureCachedHTMLCollection(TableTBodies);
569 }
570
571 const AtomicString& HTMLTableElement::rules() const
572 {
573     return getAttribute(rulesAttr);
574 }
575
576 const AtomicString& HTMLTableElement::summary() const
577 {
578     return getAttribute(summaryAttr);
579 }
580
581 void HTMLTableElement::trace(Visitor* visitor)
582 {
583     visitor->trace(m_sharedCellStyle);
584     HTMLElement::trace(visitor);
585 }
586
587 }