LayoutTests:
Based on test cases provided by Maks Orlovich.
- test for http://bugzilla.opendarwin.org/show_bug.cgi?id=4586
rowIndex calculation doesn't consider head to come before body.
* fast/table/rowindex.html: Added.
* fast/table/rowindex-expected.checksum: Added.
* fast/table/rowindex-expected.png: Added.
* fast/table/rowindex-expected.txt: Added.
WebCore:
Reviewed, redone a bit, and landed by Darin (help from Eric too).
- fix http://bugzilla.opendarwin.org/show_bug.cgi?id=4586
rowIndex calculation doesn't consider head to come before body.
Test: fast/table/rowindex.html
* khtml/html/html_tableimpl.cpp: (DOM::HTMLTableRowElementImpl::rowIndex):
Change algorithm so the rows are numbered in this order: (a) all rows in the
table header section, (b) all rows in all table body sections, (c) all rows
in the table footer section. Rows in extra table header or footer sections
don't get row numbers (rowIndex returns -1). This matches Firefox.
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@12075 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog
index 10307c8..5806ae4 100644
--- a/LayoutTests/ChangeLog
+++ b/LayoutTests/ChangeLog
@@ -1,8 +1,20 @@
+2006-01-13 Darin Adler <darin@apple.com>
+
+ Based on test cases provided by Maks Orlovich.
+
+ - test for http://bugzilla.opendarwin.org/show_bug.cgi?id=4586
+ rowIndex calculation doesn't consider head to come before body.
+
+ * fast/table/rowindex.html: Added.
+ * fast/table/rowindex-expected.checksum: Added.
+ * fast/table/rowindex-expected.png: Added.
+ * fast/table/rowindex-expected.txt: Added.
+
2006-01-13 Mark Rowe <opendarwin.org@bdash.net.nz>
Reviewed and landed by Darin.
- - test fpr http://bugzilla.opendarwin.org/show_bug.cgi?id=6509
+ - test for http://bugzilla.opendarwin.org/show_bug.cgi?id=6509
content property with supported value followed by currently unsupported open-quote displays duplicated content
* fast/css-generated-content/no-openclose-quote.html: Added.
diff --git a/LayoutTests/fast/table/rowindex-expected.checksum b/LayoutTests/fast/table/rowindex-expected.checksum
new file mode 100644
index 0000000..909aa43
--- /dev/null
+++ b/LayoutTests/fast/table/rowindex-expected.checksum
@@ -0,0 +1 @@
+e50334c8346d56b0b12772eae6000da2
\ No newline at end of file
diff --git a/LayoutTests/fast/table/rowindex-expected.png b/LayoutTests/fast/table/rowindex-expected.png
new file mode 100644
index 0000000..73dce35
--- /dev/null
+++ b/LayoutTests/fast/table/rowindex-expected.png
Binary files differ
diff --git a/LayoutTests/fast/table/rowindex-expected.txt b/LayoutTests/fast/table/rowindex-expected.txt
new file mode 100644
index 0000000..74b73c1
--- /dev/null
+++ b/LayoutTests/fast/table/rowindex-expected.txt
@@ -0,0 +1,158 @@
+layer at (0,0) size 800x600
+ RenderCanvas at (0,0) size 800x600
+layer at (0,0) size 800x600
+ RenderBlock {HTML} at (0,0) size 800x600
+ RenderBody {BODY} at (8,8) size 784x584
+ RenderBlock {P} at (0,0) size 784x12
+ RenderText {TEXT} at (0,0) size 444x12
+ text run at (0,0) width 444: "This tests rowIndex, in particular in cases where the table sections are in different orders."
+ RenderBlock {P} at (0,22) size 784x12
+ RenderText {TEXT} at (0,0) size 359x12
+ text run at (0,0) width 359: "A: This table has the header and footer before the body (\"normal\" order)."
+ RenderTable {TABLE} at (0,44) size 159x62 [border: (1px outset #808080)]
+ RenderTableSection {THEAD} at (1,1) size 0x20
+ RenderTableRow {TR} at (0,0) size 0x0
+ RenderTableCell {TD} at (2,2) size 80x16 [border: (1px inset #808080)] [r=0 c=0 rs=1 cs=1]
+ RenderText {TEXT} at (2,2) size 76x12
+ text run at (2,2) width 76: "table A, header"
+ RenderTableCell {TD} at (84,2) size 71x16 [border: (1px inset #808080)] [r=0 c=1 rs=1 cs=1]
+ RenderText {TEXT} at (2,2) size 67x12
+ text run at (2,2) width 67: "rowIndex = 0"
+ RenderTableSection {TFOOT} at (1,41) size 0x20
+ RenderTableRow {TR} at (0,0) size 0x0
+ RenderTableCell {TD} at (2,2) size 80x16 [border: (1px inset #808080)] [r=0 c=0 rs=1 cs=1]
+ RenderText {TEXT} at (2,2) size 72x12
+ text run at (2,2) width 72: "table A, footer"
+ RenderTableCell {TD} at (84,2) size 71x16 [border: (1px inset #808080)] [r=0 c=1 rs=1 cs=1]
+ RenderText {TEXT} at (2,2) size 67x12
+ text run at (2,2) width 67: "rowIndex = 2"
+ RenderTableSection {TBODY} at (1,21) size 0x20
+ RenderTableRow {TR} at (0,0) size 0x0
+ RenderTableCell {TD} at (2,2) size 80x16 [border: (1px inset #808080)] [r=0 c=0 rs=1 cs=1]
+ RenderText {TEXT} at (2,2) size 66x12
+ text run at (2,2) width 66: "table A, body"
+ RenderTableCell {TD} at (84,2) size 71x16 [border: (1px inset #808080)] [r=0 c=1 rs=1 cs=1]
+ RenderText {TEXT} at (2,2) size 67x12
+ text run at (2,2) width 67: "rowIndex = 1"
+ RenderBlock {P} at (0,116) size 784x12
+ RenderText {TEXT} at (0,0) size 356x12
+ text run at (0,0) width 356: "B: This table has the footer before the body and both before the header."
+ RenderTable {TABLE} at (0,138) size 157x62 [border: (1px outset #808080)]
+ RenderTableSection {TFOOT} at (1,41) size 0x20
+ RenderTableRow {TR} at (0,0) size 0x0
+ RenderTableCell {TD} at (2,2) size 78x16 [border: (1px inset #808080)] [r=0 c=0 rs=1 cs=1]
+ RenderText {TEXT} at (2,2) size 70x12
+ text run at (2,2) width 70: "table B, footer"
+ RenderTableCell {TD} at (82,2) size 71x16 [border: (1px inset #808080)] [r=0 c=1 rs=1 cs=1]
+ RenderText {TEXT} at (2,2) size 67x12
+ text run at (2,2) width 67: "rowIndex = 2"
+ RenderTableSection {TBODY} at (1,21) size 0x20
+ RenderTableRow {TR} at (0,0) size 0x0
+ RenderTableCell {TD} at (2,2) size 78x16 [border: (1px inset #808080)] [r=0 c=0 rs=1 cs=1]
+ RenderText {TEXT} at (2,2) size 64x12
+ text run at (2,2) width 64: "table B, body"
+ RenderTableCell {TD} at (82,2) size 71x16 [border: (1px inset #808080)] [r=0 c=1 rs=1 cs=1]
+ RenderText {TEXT} at (2,2) size 67x12
+ text run at (2,2) width 67: "rowIndex = 1"
+ RenderTableSection {THEAD} at (1,1) size 0x20
+ RenderTableRow {TR} at (0,0) size 0x0
+ RenderTableCell {TD} at (2,2) size 78x16 [border: (1px inset #808080)] [r=0 c=0 rs=1 cs=1]
+ RenderText {TEXT} at (2,2) size 74x12
+ text run at (2,2) width 74: "table B, header"
+ RenderTableCell {TD} at (82,2) size 71x16 [border: (1px inset #808080)] [r=0 c=1 rs=1 cs=1]
+ RenderText {TEXT} at (2,2) size 67x12
+ text run at (2,2) width 67: "rowIndex = 0"
+ RenderBlock {P} at (0,210) size 784x12
+ RenderText {TEXT} at (0,0) size 683x12
+ text run at (0,0) width 683: "C: This table has two footers before two bodies before two heads. The rows inside the extra footers and heads don't get row indices at all."
+ RenderTable {TABLE} at (0,232) size 206x230 [border: (1px outset #808080)]
+ RenderTableSection {TFOOT} at (1,191) size 0x38
+ RenderTableRow {TR} at (0,0) size 0x0
+ RenderTableCell {TD} at (2,2) size 121x16 [border: (1px inset #808080)] [r=0 c=0 rs=1 cs=1]
+ RenderText {TEXT} at (2,2) size 113x12
+ text run at (2,2) width 113: "table C, footer A row A"
+ RenderTableCell {TD} at (125,2) size 77x16 [border: (1px inset #808080)] [r=0 c=1 rs=1 cs=1]
+ RenderText {TEXT} at (2,2) size 67x12
+ text run at (2,2) width 67: "rowIndex = 6"
+ RenderTableRow {TR} at (0,0) size 0x0
+ RenderTableCell {TD} at (2,20) size 121x16 [border: (1px inset #808080)] [r=1 c=0 rs=1 cs=1]
+ RenderText {TEXT} at (2,2) size 112x12
+ text run at (2,2) width 112: "table C, footer A row B"
+ RenderTableCell {TD} at (125,20) size 77x16 [border: (1px inset #808080)] [r=1 c=1 rs=1 cs=1]
+ RenderText {TEXT} at (2,2) size 67x12
+ text run at (2,2) width 67: "rowIndex = 7"
+ RenderTableSection {TFOOT} at (1,39) size 0x38
+ RenderTableRow {TR} at (0,0) size 0x0
+ RenderTableCell {TD} at (2,2) size 121x16 [border: (1px inset #808080)] [r=0 c=0 rs=1 cs=1]
+ RenderText {TEXT} at (2,2) size 112x12
+ text run at (2,2) width 112: "table C, footer B row A"
+ RenderTableCell {TD} at (125,2) size 77x16 [border: (1px inset #808080)] [r=0 c=1 rs=1 cs=1]
+ RenderText {TEXT} at (2,2) size 73x12
+ text run at (2,2) width 73: "rowIndex = -1"
+ RenderTableRow {TR} at (0,0) size 0x0
+ RenderTableCell {TD} at (2,20) size 121x16 [border: (1px inset #808080)] [r=1 c=0 rs=1 cs=1]
+ RenderText {TEXT} at (2,2) size 111x12
+ text run at (2,2) width 111: "table C, footer B row B"
+ RenderTableCell {TD} at (125,20) size 77x16 [border: (1px inset #808080)] [r=1 c=1 rs=1 cs=1]
+ RenderText {TEXT} at (2,2) size 73x12
+ text run at (2,2) width 73: "rowIndex = -1"
+ RenderTableSection {TBODY} at (1,77) size 0x38
+ RenderTableRow {TR} at (0,0) size 0x0
+ RenderTableCell {TD} at (2,2) size 121x16 [border: (1px inset #808080)] [r=0 c=0 rs=1 cs=1]
+ RenderText {TEXT} at (2,2) size 107x12
+ text run at (2,2) width 107: "table C, body A row A"
+ RenderTableCell {TD} at (125,2) size 77x16 [border: (1px inset #808080)] [r=0 c=1 rs=1 cs=1]
+ RenderText {TEXT} at (2,2) size 67x12
+ text run at (2,2) width 67: "rowIndex = 2"
+ RenderTableRow {TR} at (0,0) size 0x0
+ RenderTableCell {TD} at (2,20) size 121x16 [border: (1px inset #808080)] [r=1 c=0 rs=1 cs=1]
+ RenderText {TEXT} at (2,2) size 106x12
+ text run at (2,2) width 106: "table C, body A row B"
+ RenderTableCell {TD} at (125,20) size 77x16 [border: (1px inset #808080)] [r=1 c=1 rs=1 cs=1]
+ RenderText {TEXT} at (2,2) size 67x12
+ text run at (2,2) width 67: "rowIndex = 3"
+ RenderTableSection {TBODY} at (1,115) size 0x38
+ RenderTableRow {TR} at (0,0) size 0x0
+ RenderTableCell {TD} at (2,2) size 121x16 [border: (1px inset #808080)] [r=0 c=0 rs=1 cs=1]
+ RenderText {TEXT} at (2,2) size 106x12
+ text run at (2,2) width 106: "table C, body B row A"
+ RenderTableCell {TD} at (125,2) size 77x16 [border: (1px inset #808080)] [r=0 c=1 rs=1 cs=1]
+ RenderText {TEXT} at (2,2) size 67x12
+ text run at (2,2) width 67: "rowIndex = 4"
+ RenderTableRow {TR} at (0,0) size 0x0
+ RenderTableCell {TD} at (2,20) size 121x16 [border: (1px inset #808080)] [r=1 c=0 rs=1 cs=1]
+ RenderText {TEXT} at (2,2) size 105x12
+ text run at (2,2) width 105: "table C, body B row B"
+ RenderTableCell {TD} at (125,20) size 77x16 [border: (1px inset #808080)] [r=1 c=1 rs=1 cs=1]
+ RenderText {TEXT} at (2,2) size 67x12
+ text run at (2,2) width 67: "rowIndex = 5"
+ RenderTableSection {THEAD} at (1,1) size 0x38
+ RenderTableRow {TR} at (0,0) size 0x0
+ RenderTableCell {TD} at (2,2) size 121x16 [border: (1px inset #808080)] [r=0 c=0 rs=1 cs=1]
+ RenderText {TEXT} at (2,2) size 117x12
+ text run at (2,2) width 117: "table C, header A row A"
+ RenderTableCell {TD} at (125,2) size 77x16 [border: (1px inset #808080)] [r=0 c=1 rs=1 cs=1]
+ RenderText {TEXT} at (2,2) size 67x12
+ text run at (2,2) width 67: "rowIndex = 0"
+ RenderTableRow {TR} at (0,0) size 0x0
+ RenderTableCell {TD} at (2,20) size 121x16 [border: (1px inset #808080)] [r=1 c=0 rs=1 cs=1]
+ RenderText {TEXT} at (2,2) size 116x12
+ text run at (2,2) width 116: "table C, header A row B"
+ RenderTableCell {TD} at (125,20) size 77x16 [border: (1px inset #808080)] [r=1 c=1 rs=1 cs=1]
+ RenderText {TEXT} at (2,2) size 67x12
+ text run at (2,2) width 67: "rowIndex = 1"
+ RenderTableSection {THEAD} at (1,153) size 0x38
+ RenderTableRow {TR} at (0,0) size 0x0
+ RenderTableCell {TD} at (2,2) size 121x16 [border: (1px inset #808080)] [r=0 c=0 rs=1 cs=1]
+ RenderText {TEXT} at (2,2) size 116x12
+ text run at (2,2) width 116: "table C, header B row A"
+ RenderTableCell {TD} at (125,2) size 77x16 [border: (1px inset #808080)] [r=0 c=1 rs=1 cs=1]
+ RenderText {TEXT} at (2,2) size 73x12
+ text run at (2,2) width 73: "rowIndex = -1"
+ RenderTableRow {TR} at (0,0) size 0x0
+ RenderTableCell {TD} at (2,20) size 121x16 [border: (1px inset #808080)] [r=1 c=0 rs=1 cs=1]
+ RenderText {TEXT} at (2,2) size 115x12
+ text run at (2,2) width 115: "table C, header B row B"
+ RenderTableCell {TD} at (125,20) size 77x16 [border: (1px inset #808080)] [r=1 c=1 rs=1 cs=1]
+ RenderText {TEXT} at (2,2) size 73x12
+ text run at (2,2) width 73: "rowIndex = -1"
diff --git a/LayoutTests/fast/table/rowindex.html b/LayoutTests/fast/table/rowindex.html
new file mode 100644
index 0000000..30bf57f
--- /dev/null
+++ b/LayoutTests/fast/table/rowindex.html
@@ -0,0 +1,53 @@
+<head>
+
+<style>
+
+body, table { font-family: "Lucida Grande"; font-size: 10px }
+
+</style>
+
+<script>
+
+function labelRows()
+{
+ rows = document.getElementsByTagName("tr");
+ for (i = 0; i < rows.length; ++i)
+ rows[i].innerHTML += "<td>" + rows[i].id + "</td><td>rowIndex = " + rows[i].rowIndex + "</td>"
+}
+
+</script>
+
+</head>
+
+<body onload="labelRows()">
+
+<p>This tests rowIndex, in particular in cases where the table sections are in different orders.</p>
+
+<p>A: This table has the header and footer before the body ("normal" order).</p>
+
+<table border=1>
+ <thead><tr id="table A, header"></tr></thead>
+ <tfoot><tr id="table A, footer"></tr></tfoot>
+ <tbody><tr id="table A, body"></tr></tbody>
+</table>
+
+<p>B: This table has the footer before the body and both before the header.</p>
+
+<table border=1>
+ <tfoot><tr id="table B, footer"></tr></tfoot>
+ <tbody><tr id="table B, body"></tr></tbody>
+ <thead><tr id="table B, header"></tr></thead>
+</table>
+
+<p>C: This table has two footers before two bodies before two heads. The rows inside the extra footers and heads don't get row indices at all.</p>
+
+<table border=1>
+ <tfoot><tr id="table C, footer A row A"></tr><tr id="table C, footer A row B"></tr></tfoot>
+ <tfoot><tr id="table C, footer B row A"></tr><tr id="table C, footer B row B"></tr></tfoot>
+ <tbody><tr id="table C, body A row A"></tr><tr id="table C, body A row B"></tr></tfoot>
+ <tbody><tr id="table C, body B row A"></tr><tr id="table C, body B row B"></tr></tfoot>
+ <thead><tr id="table C, header A row A"></tr><tr id="table C, header A row B"></tr></tfoot>
+ <thead><tr id="table C, header B row A"></tr><tr id="table C, header B row B"></tr></tfoot>
+</table>
+
+</body>
diff --git a/WebCore/ChangeLog b/WebCore/ChangeLog
index f71b5f2..0ad70e7 100644
--- a/WebCore/ChangeLog
+++ b/WebCore/ChangeLog
@@ -1,3 +1,18 @@
+2006-01-13 Maks Orlovich <maksim@kde.org>
+
+ Reviewed, redone a bit, and landed by Darin (help from Eric too).
+
+ - fix http://bugzilla.opendarwin.org/show_bug.cgi?id=4586
+ rowIndex calculation doesn't consider head to come before body.
+
+ Test: fast/table/rowindex.html
+
+ * khtml/html/html_tableimpl.cpp: (DOM::HTMLTableRowElementImpl::rowIndex):
+ Change algorithm so the rows are numbered in this order: (a) all rows in the
+ table header section, (b) all rows in all table body sections, (c) all rows
+ in the table footer section. Rows in extra table header or footer sections
+ don't get row numbers (rowIndex returns -1). This matches Firefox.
+
2006-01-13 Mark Rowe <opendarwin.org@bdash.net.nz>
Reviewed, tweaked, and landed by Darin.
diff --git a/WebCore/khtml/html/html_tableimpl.cpp b/WebCore/khtml/html/html_tableimpl.cpp
index 20caf14..098cb18 100644
--- a/WebCore/khtml/html/html_tableimpl.cpp
+++ b/WebCore/khtml/html/html_tableimpl.cpp
@@ -237,8 +237,8 @@
bool found = false;
for ( ; node && (index>=0 || append) ; node = node->nextSibling() )
{
- // there could be 2 tfoot elements in the table. Only the first one is the "foot", that's why we have the more
- // complicated if statement below.
+ // there could be 2 tfoot elements in the table. Only the first one is the "foot", that's why we have the more
+ // complicated if statement below.
if (node != foot && (node->hasTagName(theadTag) || node->hasTagName(tfootTag) || node->hasTagName(tbodyTag)))
{
section = static_cast<HTMLTableSectionElementImpl *>(node);
@@ -248,7 +248,7 @@
{
int rows = section->numRows();
if (rows >= index) {
- found = true;
+ found = true;
break;
} else
index -= rows;
@@ -349,8 +349,8 @@
head = static_cast<HTMLTableSectionElementImpl *>(child);
else if (!foot && child->hasTagName(tfootTag))
foot = static_cast<HTMLTableSectionElementImpl *>(child);
- else if (!firstBody && child->hasTagName(tbodyTag)) {
- firstBody = static_cast<HTMLTableSectionElementImpl *>(child);
+ else if (!firstBody && child->hasTagName(tbodyTag)) {
+ firstBody = static_cast<HTMLTableSectionElementImpl *>(child);
firstBody->ref();
}
}
@@ -465,8 +465,8 @@
padding = 1;
if (m_render && m_render->isTable()) {
static_cast<RenderTable *>(m_render)->setCellPadding(padding);
- if (!m_render->needsLayout())
- m_render->setNeedsLayout(true);
+ if (!m_render->needsLayout())
+ m_render->setNeedsLayout(true);
}
} else if (attr->name() == colsAttr) {
// ###
@@ -551,7 +551,7 @@
assert(!m_attached);
HTMLElementImpl::attach();
if ( m_render && m_render->isTable() )
- static_cast<RenderTable *>(m_render)->setCellPadding( padding );
+ static_cast<RenderTable *>(m_render)->setCellPadding( padding );
}
bool HTMLTableElementImpl::isURLAttribute(AttributeImpl *attr) const
@@ -755,7 +755,6 @@
HTMLTableRowElementImpl *r = 0L;
RefPtr<NodeListImpl> children = childNodes();
int numRows = children ? (int)children->length() : 0;
- //kdDebug(6030) << k_funcinfo << "index=" << index << " numRows=" << numRows << endl;
if ( index < -1 || index > numRows ) {
exceptioncode = DOMException::INDEX_SIZE_ERR; // per the DOM
}
@@ -870,38 +869,48 @@
int HTMLTableRowElementImpl::rowIndex() const
{
- int rIndex = 0;
-
NodeImpl *table = parentNode();
if (!table)
- return -1;
+ return -1;
table = table->parentNode();
if (!table || !table->hasTagName(tableTag))
- return -1;
+ return -1;
- HTMLTableSectionElementImpl *foot = static_cast<HTMLTableElementImpl *>(table)->tFoot();
- NodeImpl *node = table->firstChild();
- while (node) {
- if (node != foot && (node->hasTagName(theadTag) || node->hasTagName(tfootTag) || node->hasTagName(tbodyTag))) {
- HTMLTableSectionElementImpl* section = static_cast<HTMLTableSectionElementImpl *>(node);
- const NodeImpl *row = section->firstChild();
- while ( row ) {
- if ( row == this )
- return rIndex;
- rIndex++;
- row = row->nextSibling();
- }
- }
- node = node->nextSibling();
+ // To match Firefox, the row indices work like this:
+ // Rows from the first <thead> are numbered before all <tbody> rows.
+ // Rows from the first <tfoot> are numbered after all <tbody> rows.
+ // Rows from other <thead> and <tfoot> elements don't get row indices at all.
+
+ int rIndex = 0;
+
+ if (HTMLTableSectionElementImpl* head = static_cast<HTMLTableElementImpl*>(table)->tHead()) {
+ for (NodeImpl *row = head->firstChild(); row; row = row->nextSibling()) {
+ if (row == this)
+ return rIndex;
+ ++rIndex;
+ }
}
- const NodeImpl *row = foot->firstChild();
- while ( row ) {
- if ( row == this )
- return rIndex;
- rIndex++;
- row = row->nextSibling();
+
+ for (NodeImpl *node = table->firstChild(); node; node = node->nextSibling()) {
+ if (node->hasTagName(tbodyTag)) {
+ HTMLTableSectionElementImpl* section = static_cast<HTMLTableSectionElementImpl*>(node);
+ for (NodeImpl* row = section->firstChild(); row; row = row->nextSibling()) {
+ if (row == this)
+ return rIndex;
+ ++rIndex;
+ }
+ }
}
- // should never happen
+
+ if (HTMLTableSectionElementImpl* foot = static_cast<HTMLTableElementImpl *>(table)->tFoot()) {
+ for (NodeImpl *row = foot->firstChild(); row; row = row->nextSibling()) {
+ if (row == this)
+ return rIndex;
+ ++rIndex;
+ }
+ }
+
+ // We get here for rows that are in <thead> or <tfoot> sections other than the main header and footer.
return -1;
}