PageRenderTime 27ms CodeModel.GetById 12ms RepoModel.GetById 1ms app.codeStats 0ms

/Source/core/html/HTMLTableElement.cpp

https://repo.or.cz/blink.git
C++ | 568 lines | 470 code | 63 blank | 35 comment | 168 complexity | 0af6ca7413d74f96d7732bedace4eff4 MD5 | raw file
Possible License(s): BSD-3-Clause, Unlicense, AGPL-1.0, Apache-2.0
  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. #include "config.h"
  25. #include "core/html/HTMLTableElement.h"
  26. #include "bindings/core/v8/ExceptionState.h"
  27. #include "bindings/core/v8/ExceptionStatePlaceholder.h"
  28. #include "core/CSSPropertyNames.h"
  29. #include "core/CSSValueKeywords.h"
  30. #include "core/HTMLNames.h"
  31. #include "core/css/CSSImageValue.h"
  32. #include "core/css/CSSValuePool.h"
  33. #include "core/dom/Attribute.h"
  34. #include "core/dom/ElementTraversal.h"
  35. #include "core/dom/NodeListsNodeData.h"
  36. #include "core/html/HTMLTableCaptionElement.h"
  37. #include "core/html/HTMLTableCellElement.h"
  38. #include "core/html/HTMLTableRowElement.h"
  39. #include "core/html/HTMLTableRowsCollection.h"
  40. #include "core/html/HTMLTableSectionElement.h"
  41. #include "core/html/parser/HTMLParserIdioms.h"
  42. #include "core/layout/LayoutTable.h"
  43. #include "platform/weborigin/Referrer.h"
  44. #include "wtf/StdLibExtras.h"
  45. namespace blink {
  46. using namespace HTMLNames;
  47. inline HTMLTableElement::HTMLTableElement(Document& document)
  48. : HTMLElement(tableTag, document)
  49. , m_borderAttr(false)
  50. , m_borderColorAttr(false)
  51. , m_frameAttr(false)
  52. , m_rulesAttr(UnsetRules)
  53. , m_padding(1)
  54. {
  55. }
  56. // An explicit empty destructor should be in HTMLTableElement.cpp, because
  57. // if an implicit destructor is used or an empty destructor is defined in
  58. // HTMLTableElement.h, when including HTMLTableElement, msvc tries to expand
  59. // the destructor and causes a compile error because of lack of
  60. // StylePropertySet definition.
  61. HTMLTableElement::~HTMLTableElement()
  62. {
  63. }
  64. DEFINE_NODE_FACTORY(HTMLTableElement)
  65. HTMLTableCaptionElement* HTMLTableElement::caption() const
  66. {
  67. return Traversal<HTMLTableCaptionElement>::firstChild(*this);
  68. }
  69. void HTMLTableElement::setCaption(PassRefPtrWillBeRawPtr<HTMLTableCaptionElement> newCaption, ExceptionState& exceptionState)
  70. {
  71. deleteCaption();
  72. insertBefore(newCaption, firstChild(), exceptionState);
  73. }
  74. HTMLTableSectionElement* HTMLTableElement::tHead() const
  75. {
  76. return toHTMLTableSectionElement(Traversal<HTMLElement>::firstChild(*this, HasHTMLTagName(theadTag)));
  77. }
  78. void HTMLTableElement::setTHead(PassRefPtrWillBeRawPtr<HTMLTableSectionElement> newHead, ExceptionState& exceptionState)
  79. {
  80. deleteTHead();
  81. HTMLElement* child;
  82. for (child = Traversal<HTMLElement>::firstChild(*this); child; child = Traversal<HTMLElement>::nextSibling(*child)) {
  83. if (!child->hasTagName(captionTag) && !child->hasTagName(colgroupTag))
  84. break;
  85. }
  86. insertBefore(newHead, child, exceptionState);
  87. }
  88. HTMLTableSectionElement* HTMLTableElement::tFoot() const
  89. {
  90. return toHTMLTableSectionElement(Traversal<HTMLElement>::firstChild(*this, HasHTMLTagName(tfootTag)));
  91. }
  92. void HTMLTableElement::setTFoot(PassRefPtrWillBeRawPtr<HTMLTableSectionElement> newFoot, ExceptionState& exceptionState)
  93. {
  94. deleteTFoot();
  95. HTMLElement* child;
  96. for (child = Traversal<HTMLElement>::firstChild(*this); child; child = Traversal<HTMLElement>::nextSibling(*child)) {
  97. if (!child->hasTagName(captionTag) && !child->hasTagName(colgroupTag) && !child->hasTagName(theadTag))
  98. break;
  99. }
  100. insertBefore(newFoot, child, exceptionState);
  101. }
  102. PassRefPtrWillBeRawPtr<HTMLElement> HTMLTableElement::createTHead()
  103. {
  104. if (HTMLTableSectionElement* existingHead = tHead())
  105. return existingHead;
  106. RefPtrWillBeRawPtr<HTMLTableSectionElement> head = HTMLTableSectionElement::create(theadTag, document());
  107. setTHead(head, IGNORE_EXCEPTION);
  108. return head.release();
  109. }
  110. void HTMLTableElement::deleteTHead()
  111. {
  112. removeChild(tHead(), IGNORE_EXCEPTION);
  113. }
  114. PassRefPtrWillBeRawPtr<HTMLElement> HTMLTableElement::createTFoot()
  115. {
  116. if (HTMLTableSectionElement* existingFoot = tFoot())
  117. return existingFoot;
  118. RefPtrWillBeRawPtr<HTMLTableSectionElement> foot = HTMLTableSectionElement::create(tfootTag, document());
  119. setTFoot(foot, IGNORE_EXCEPTION);
  120. return foot.release();
  121. }
  122. void HTMLTableElement::deleteTFoot()
  123. {
  124. removeChild(tFoot(), IGNORE_EXCEPTION);
  125. }
  126. PassRefPtrWillBeRawPtr<HTMLElement> HTMLTableElement::createTBody()
  127. {
  128. RefPtrWillBeRawPtr<HTMLTableSectionElement> body = HTMLTableSectionElement::create(tbodyTag, document());
  129. Node* referenceElement = lastBody() ? lastBody()->nextSibling() : 0;
  130. insertBefore(body, referenceElement);
  131. return body.release();
  132. }
  133. PassRefPtrWillBeRawPtr<HTMLElement> HTMLTableElement::createCaption()
  134. {
  135. if (HTMLTableCaptionElement* existingCaption = caption())
  136. return existingCaption;
  137. RefPtrWillBeRawPtr<HTMLTableCaptionElement> caption = HTMLTableCaptionElement::create(document());
  138. setCaption(caption, IGNORE_EXCEPTION);
  139. return caption.release();
  140. }
  141. void HTMLTableElement::deleteCaption()
  142. {
  143. removeChild(caption(), IGNORE_EXCEPTION);
  144. }
  145. HTMLTableSectionElement* HTMLTableElement::lastBody() const
  146. {
  147. return toHTMLTableSectionElement(Traversal<HTMLElement>::lastChild(*this, HasHTMLTagName(tbodyTag)));
  148. }
  149. PassRefPtrWillBeRawPtr<HTMLElement> HTMLTableElement::insertRow(int index, ExceptionState& exceptionState)
  150. {
  151. if (index < -1) {
  152. exceptionState.throwDOMException(IndexSizeError, "The index provided (" + String::number(index) + ") is less than -1.");
  153. return nullptr;
  154. }
  155. RefPtrWillBeRawPtr<Node> protectFromMutationEvents(this);
  156. RefPtrWillBeRawPtr<HTMLTableRowElement> lastRow = nullptr;
  157. RefPtrWillBeRawPtr<HTMLTableRowElement> row = nullptr;
  158. if (index == -1) {
  159. lastRow = HTMLTableRowsCollection::lastRow(*this);
  160. } else {
  161. for (int i = 0; i <= index; ++i) {
  162. row = HTMLTableRowsCollection::rowAfter(*this, lastRow.get());
  163. if (!row) {
  164. if (i != index) {
  165. exceptionState.throwDOMException(IndexSizeError, "The index provided (" + String::number(index) + ") is greater than the number of rows in the table (" + String::number(i) + ").");
  166. return nullptr;
  167. }
  168. break;
  169. }
  170. lastRow = row;
  171. }
  172. }
  173. RefPtrWillBeRawPtr<ContainerNode> parent;
  174. if (lastRow) {
  175. parent = row ? row->parentNode() : lastRow->parentNode();
  176. } else {
  177. parent = lastBody();
  178. if (!parent) {
  179. RefPtrWillBeRawPtr<HTMLTableSectionElement> newBody = HTMLTableSectionElement::create(tbodyTag, document());
  180. RefPtrWillBeRawPtr<HTMLTableRowElement> newRow = HTMLTableRowElement::create(document());
  181. newBody->appendChild(newRow, exceptionState);
  182. appendChild(newBody.release(), exceptionState);
  183. return newRow.release();
  184. }
  185. }
  186. RefPtrWillBeRawPtr<HTMLTableRowElement> newRow = HTMLTableRowElement::create(document());
  187. parent->insertBefore(newRow, row.get(), exceptionState);
  188. return newRow.release();
  189. }
  190. void HTMLTableElement::deleteRow(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;
  195. }
  196. HTMLTableRowElement* row = 0;
  197. int i = 0;
  198. if (index == -1) {
  199. row = HTMLTableRowsCollection::lastRow(*this);
  200. } else {
  201. for (i = 0; i <= index; ++i) {
  202. row = HTMLTableRowsCollection::rowAfter(*this, row);
  203. if (!row)
  204. break;
  205. }
  206. }
  207. if (!row) {
  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;
  210. }
  211. row->remove(exceptionState);
  212. }
  213. void HTMLTableElement::setNeedsTableStyleRecalc() const
  214. {
  215. Element* element = ElementTraversal::next(*this, this);
  216. while (element) {
  217. element->setNeedsStyleRecalc(LocalStyleChange, StyleChangeReasonForTracing::fromAttribute(rulesAttr));
  218. if (isHTMLTableCellElement(*element))
  219. element = ElementTraversal::nextSkippingChildren(*element, this);
  220. else
  221. element = ElementTraversal::next(*element, this);
  222. }
  223. }
  224. static bool getBordersFromFrameAttributeValue(const AtomicString& value, bool& borderTop, bool& borderRight, bool& borderBottom, bool& borderLeft)
  225. {
  226. borderTop = false;
  227. borderRight = false;
  228. borderBottom = false;
  229. borderLeft = false;
  230. if (equalIgnoringCase(value, "above"))
  231. borderTop = true;
  232. else if (equalIgnoringCase(value, "below"))
  233. borderBottom = true;
  234. else if (equalIgnoringCase(value, "hsides"))
  235. borderTop = borderBottom = true;
  236. else if (equalIgnoringCase(value, "vsides"))
  237. borderLeft = borderRight = true;
  238. else if (equalIgnoringCase(value, "lhs"))
  239. borderLeft = true;
  240. else if (equalIgnoringCase(value, "rhs"))
  241. borderRight = true;
  242. else if (equalIgnoringCase(value, "box") || equalIgnoringCase(value, "border"))
  243. borderTop = borderBottom = borderLeft = borderRight = true;
  244. else if (!equalIgnoringCase(value, "void"))
  245. return false;
  246. return true;
  247. }
  248. void HTMLTableElement::collectStyleForPresentationAttribute(const QualifiedName& name, const AtomicString& value, MutableStylePropertySet* style)
  249. {
  250. if (name == widthAttr) {
  251. addHTMLLengthToStyle(style, CSSPropertyWidth, value);
  252. } else if (name == heightAttr) {
  253. addHTMLLengthToStyle(style, CSSPropertyHeight, value);
  254. } else if (name == borderAttr) {
  255. addPropertyToPresentationAttributeStyle(style, CSSPropertyBorderWidth, parseBorderWidthAttribute(value), CSSPrimitiveValue::UnitType::Pixels);
  256. } else if (name == bordercolorAttr) {
  257. if (!value.isEmpty())
  258. addHTMLColorToStyle(style, CSSPropertyBorderColor, value);
  259. } else if (name == bgcolorAttr) {
  260. addHTMLColorToStyle(style, CSSPropertyBackgroundColor, value);
  261. } else if (name == backgroundAttr) {
  262. String url = stripLeadingAndTrailingHTMLSpaces(value);
  263. if (!url.isEmpty()) {
  264. RefPtrWillBeRawPtr<CSSImageValue> imageValue = CSSImageValue::create(url, document().completeURL(url));
  265. imageValue->setReferrer(Referrer(document().outgoingReferrer(), document().referrerPolicy()));
  266. style->setProperty(CSSProperty(CSSPropertyBackgroundImage, imageValue.release()));
  267. }
  268. } else if (name == valignAttr) {
  269. if (!value.isEmpty())
  270. addPropertyToPresentationAttributeStyle(style, CSSPropertyVerticalAlign, value);
  271. } else if (name == cellspacingAttr) {
  272. if (!value.isEmpty())
  273. addHTMLLengthToStyle(style, CSSPropertyBorderSpacing, value);
  274. } else if (name == alignAttr) {
  275. if (!value.isEmpty()) {
  276. if (equalIgnoringCase(value, "center")) {
  277. addPropertyToPresentationAttributeStyle(style, CSSPropertyWebkitMarginStart, CSSValueAuto);
  278. addPropertyToPresentationAttributeStyle(style, CSSPropertyWebkitMarginEnd, CSSValueAuto);
  279. } else {
  280. addPropertyToPresentationAttributeStyle(style, CSSPropertyFloat, value);
  281. }
  282. }
  283. } else if (name == rulesAttr) {
  284. // The presence of a valid rules attribute causes border collapsing to be enabled.
  285. if (m_rulesAttr != UnsetRules)
  286. addPropertyToPresentationAttributeStyle(style, CSSPropertyBorderCollapse, CSSValueCollapse);
  287. } else if (name == frameAttr) {
  288. bool borderTop;
  289. bool borderRight;
  290. bool borderBottom;
  291. bool borderLeft;
  292. if (getBordersFromFrameAttributeValue(value, borderTop, borderRight, borderBottom, borderLeft)) {
  293. addPropertyToPresentationAttributeStyle(style, CSSPropertyBorderWidth, CSSValueThin);
  294. addPropertyToPresentationAttributeStyle(style, CSSPropertyBorderTopStyle, borderTop ? CSSValueSolid : CSSValueHidden);
  295. addPropertyToPresentationAttributeStyle(style, CSSPropertyBorderBottomStyle, borderBottom ? CSSValueSolid : CSSValueHidden);
  296. addPropertyToPresentationAttributeStyle(style, CSSPropertyBorderLeftStyle, borderLeft ? CSSValueSolid : CSSValueHidden);
  297. addPropertyToPresentationAttributeStyle(style, CSSPropertyBorderRightStyle, borderRight ? CSSValueSolid : CSSValueHidden);
  298. }
  299. } else {
  300. HTMLElement::collectStyleForPresentationAttribute(name, value, style);
  301. }
  302. }
  303. bool HTMLTableElement::isPresentationAttribute(const QualifiedName& name) const
  304. {
  305. 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)
  306. return true;
  307. return HTMLElement::isPresentationAttribute(name);
  308. }
  309. void HTMLTableElement::parseAttribute(const QualifiedName& name, const AtomicString& value)
  310. {
  311. CellBorders bordersBefore = cellBorders();
  312. unsigned short oldPadding = m_padding;
  313. if (name == borderAttr) {
  314. // FIXME: This attribute is a mess.
  315. m_borderAttr = parseBorderWidthAttribute(value);
  316. } else if (name == bordercolorAttr) {
  317. m_borderColorAttr = !value.isEmpty();
  318. } else if (name == frameAttr) {
  319. // FIXME: This attribute is a mess.
  320. bool borderTop;
  321. bool borderRight;
  322. bool borderBottom;
  323. bool borderLeft;
  324. m_frameAttr = getBordersFromFrameAttributeValue(value, borderTop, borderRight, borderBottom, borderLeft);
  325. } else if (name == rulesAttr) {
  326. m_rulesAttr = UnsetRules;
  327. if (equalIgnoringCase(value, "none"))
  328. m_rulesAttr = NoneRules;
  329. else if (equalIgnoringCase(value, "groups"))
  330. m_rulesAttr = GroupsRules;
  331. else if (equalIgnoringCase(value, "rows"))
  332. m_rulesAttr = RowsRules;
  333. else if (equalIgnoringCase(value, "cols"))
  334. m_rulesAttr = ColsRules;
  335. else if (equalIgnoringCase(value, "all"))
  336. m_rulesAttr = AllRules;
  337. } else if (name == cellpaddingAttr) {
  338. if (!value.isEmpty())
  339. m_padding = max(0, value.toInt());
  340. else
  341. m_padding = 1;
  342. } else if (name == colsAttr) {
  343. // ###
  344. } else {
  345. HTMLElement::parseAttribute(name, value);
  346. }
  347. if (bordersBefore != cellBorders() || oldPadding != m_padding) {
  348. m_sharedCellStyle = nullptr;
  349. setNeedsTableStyleRecalc();
  350. }
  351. }
  352. static PassRefPtrWillBeRawPtr<StylePropertySet> createBorderStyle(CSSValueID value)
  353. {
  354. RefPtrWillBeRawPtr<MutableStylePropertySet> style = MutableStylePropertySet::create(HTMLQuirksMode);
  355. style->setProperty(CSSPropertyBorderTopStyle, value);
  356. style->setProperty(CSSPropertyBorderBottomStyle, value);
  357. style->setProperty(CSSPropertyBorderLeftStyle, value);
  358. style->setProperty(CSSPropertyBorderRightStyle, value);
  359. return style.release();
  360. }
  361. const StylePropertySet* HTMLTableElement::additionalPresentationAttributeStyle()
  362. {
  363. if (m_frameAttr)
  364. return nullptr;
  365. if (!m_borderAttr && !m_borderColorAttr) {
  366. // Setting the border to 'hidden' allows it to win over any border
  367. // set on the table's cells during border-conflict resolution.
  368. if (m_rulesAttr != UnsetRules) {
  369. DEFINE_STATIC_REF_WILL_BE_PERSISTENT(StylePropertySet, solidBorderStyle, (createBorderStyle(CSSValueHidden)));
  370. return solidBorderStyle;
  371. }
  372. return nullptr;
  373. }
  374. if (m_borderColorAttr) {
  375. DEFINE_STATIC_REF_WILL_BE_PERSISTENT(StylePropertySet, solidBorderStyle, (createBorderStyle(CSSValueSolid)));
  376. return solidBorderStyle;
  377. }
  378. DEFINE_STATIC_REF_WILL_BE_PERSISTENT(StylePropertySet, outsetBorderStyle, (createBorderStyle(CSSValueOutset)));
  379. return outsetBorderStyle;
  380. }
  381. HTMLTableElement::CellBorders HTMLTableElement::cellBorders() const
  382. {
  383. switch (m_rulesAttr) {
  384. case NoneRules:
  385. case GroupsRules:
  386. return NoBorders;
  387. case AllRules:
  388. return SolidBorders;
  389. case ColsRules:
  390. return SolidBordersColsOnly;
  391. case RowsRules:
  392. return SolidBordersRowsOnly;
  393. case UnsetRules:
  394. if (!m_borderAttr)
  395. return NoBorders;
  396. if (m_borderColorAttr)
  397. return SolidBorders;
  398. return InsetBorders;
  399. }
  400. ASSERT_NOT_REACHED();
  401. return NoBorders;
  402. }
  403. PassRefPtrWillBeRawPtr<StylePropertySet> HTMLTableElement::createSharedCellStyle()
  404. {
  405. RefPtrWillBeRawPtr<MutableStylePropertySet> style = MutableStylePropertySet::create(HTMLQuirksMode);
  406. switch (cellBorders()) {
  407. case SolidBordersColsOnly:
  408. style->setProperty(CSSPropertyBorderLeftWidth, CSSValueThin);
  409. style->setProperty(CSSPropertyBorderRightWidth, CSSValueThin);
  410. style->setProperty(CSSPropertyBorderLeftStyle, CSSValueSolid);
  411. style->setProperty(CSSPropertyBorderRightStyle, CSSValueSolid);
  412. style->setProperty(CSSPropertyBorderColor, cssValuePool().createInheritedValue());
  413. break;
  414. case SolidBordersRowsOnly:
  415. style->setProperty(CSSPropertyBorderTopWidth, CSSValueThin);
  416. style->setProperty(CSSPropertyBorderBottomWidth, CSSValueThin);
  417. style->setProperty(CSSPropertyBorderTopStyle, CSSValueSolid);
  418. style->setProperty(CSSPropertyBorderBottomStyle, CSSValueSolid);
  419. style->setProperty(CSSPropertyBorderColor, cssValuePool().createInheritedValue());
  420. break;
  421. case SolidBorders:
  422. style->setProperty(CSSPropertyBorderWidth, cssValuePool().createValue(1, CSSPrimitiveValue::UnitType::Pixels));
  423. style->setProperty(CSSPropertyBorderStyle, cssValuePool().createIdentifierValue(CSSValueSolid));
  424. style->setProperty(CSSPropertyBorderColor, cssValuePool().createInheritedValue());
  425. break;
  426. case InsetBorders:
  427. style->setProperty(CSSPropertyBorderWidth, cssValuePool().createValue(1, CSSPrimitiveValue::UnitType::Pixels));
  428. style->setProperty(CSSPropertyBorderStyle, cssValuePool().createIdentifierValue(CSSValueInset));
  429. style->setProperty(CSSPropertyBorderColor, cssValuePool().createInheritedValue());
  430. break;
  431. case NoBorders:
  432. // If 'rules=none' then allow any borders set at cell level to take effect.
  433. break;
  434. }
  435. if (m_padding)
  436. style->setProperty(CSSPropertyPadding, cssValuePool().createValue(m_padding, CSSPrimitiveValue::UnitType::Pixels));
  437. return style.release();
  438. }
  439. const StylePropertySet* HTMLTableElement::additionalCellStyle()
  440. {
  441. if (!m_sharedCellStyle)
  442. m_sharedCellStyle = createSharedCellStyle();
  443. return m_sharedCellStyle.get();
  444. }
  445. static PassRefPtrWillBeRawPtr<StylePropertySet> createGroupBorderStyle(int rows)
  446. {
  447. RefPtrWillBeRawPtr<MutableStylePropertySet> style = MutableStylePropertySet::create(HTMLQuirksMode);
  448. if (rows) {
  449. style->setProperty(CSSPropertyBorderTopWidth, CSSValueThin);
  450. style->setProperty(CSSPropertyBorderBottomWidth, CSSValueThin);
  451. style->setProperty(CSSPropertyBorderTopStyle, CSSValueSolid);
  452. style->setProperty(CSSPropertyBorderBottomStyle, CSSValueSolid);
  453. } else {
  454. style->setProperty(CSSPropertyBorderLeftWidth, CSSValueThin);
  455. style->setProperty(CSSPropertyBorderRightWidth, CSSValueThin);
  456. style->setProperty(CSSPropertyBorderLeftStyle, CSSValueSolid);
  457. style->setProperty(CSSPropertyBorderRightStyle, CSSValueSolid);
  458. }
  459. return style.release();
  460. }
  461. const StylePropertySet* HTMLTableElement::additionalGroupStyle(bool rows)
  462. {
  463. if (m_rulesAttr != GroupsRules)
  464. return nullptr;
  465. if (rows) {
  466. DEFINE_STATIC_REF_WILL_BE_PERSISTENT(StylePropertySet, rowBorderStyle, (createGroupBorderStyle(true)));
  467. return rowBorderStyle;
  468. }
  469. DEFINE_STATIC_REF_WILL_BE_PERSISTENT(StylePropertySet, columnBorderStyle, (createGroupBorderStyle(false)));
  470. return columnBorderStyle;
  471. }
  472. bool HTMLTableElement::isURLAttribute(const Attribute& attribute) const
  473. {
  474. return attribute.name() == backgroundAttr || HTMLElement::isURLAttribute(attribute);
  475. }
  476. bool HTMLTableElement::hasLegalLinkAttribute(const QualifiedName& name) const
  477. {
  478. return name == backgroundAttr || HTMLElement::hasLegalLinkAttribute(name);
  479. }
  480. const QualifiedName& HTMLTableElement::subResourceAttributeName() const
  481. {
  482. return backgroundAttr;
  483. }
  484. PassRefPtrWillBeRawPtr<HTMLTableRowsCollection> HTMLTableElement::rows()
  485. {
  486. return ensureCachedCollection<HTMLTableRowsCollection>(TableRows);
  487. }
  488. PassRefPtrWillBeRawPtr<HTMLCollection> HTMLTableElement::tBodies()
  489. {
  490. return ensureCachedCollection<HTMLCollection>(TableTBodies);
  491. }
  492. const AtomicString& HTMLTableElement::rules() const
  493. {
  494. return getAttribute(rulesAttr);
  495. }
  496. const AtomicString& HTMLTableElement::summary() const
  497. {
  498. return getAttribute(summaryAttr);
  499. }
  500. DEFINE_TRACE(HTMLTableElement)
  501. {
  502. visitor->trace(m_sharedCellStyle);
  503. HTMLElement::trace(visitor);
  504. }
  505. }