diff --git a/lib/commons/table/get-headers.js b/lib/commons/table/get-headers.js index e7d2131c1d..a3540dff9f 100644 --- a/lib/commons/table/get-headers.js +++ b/lib/commons/table/get-headers.js @@ -20,7 +20,14 @@ function traverseForHeaders(headerType, position, tableGrid) { // adjust position by rowspan and colspan // subtract 1 from col/rowspan to make them 0 indexed const colspan = startCell.colSpan - 1; - const rowspan = startCell.rowSpan - 1; + + // ie11 returns 1 as the rowspan value even if it's set to 0 + const rowspanAttr = startCell.getAttribute('rowspan'); + const rowspanValue = + parseInt(rowspanAttr) === 0 || startCell.rowspan === 0 + ? tableGrid.length + : startCell.rowSpan; + const rowspan = rowspanValue - 1; const rowStart = position.y + rowspan; const colStart = position.x + colspan; diff --git a/lib/commons/table/to-grid.js b/lib/commons/table/to-grid.js index 484226e0bd..0463c491cf 100644 --- a/lib/commons/table/to-grid.js +++ b/lib/commons/table/to-grid.js @@ -19,7 +19,18 @@ function toGrid(node) { for (var j = 0, cellLength = cells.length; j < cellLength; j++) { for (var colSpan = 0; colSpan < cells[j].colSpan; colSpan++) { - for (var rowSpan = 0; rowSpan < cells[j].rowSpan; rowSpan++) { + // if [the rowSpan] value is set to 0, it extends until the + // end of the table section + // @see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/td#attr-rowspan + + // ie11 returns 1 as the rowspan value even if it's set to 0 + const rowspanAttr = cells[j].getAttribute('rowspan'); + const rowspanValue = + parseInt(rowspanAttr) === 0 || cells[j].rowspan === 0 + ? rows.length + : cells[j].rowSpan; + + for (var rowSpan = 0; rowSpan < rowspanValue; rowSpan++) { table[i + rowSpan] = table[i + rowSpan] || []; while (table[i + rowSpan][columnIndex]) { columnIndex++; diff --git a/test/commons/table/get-headers.js b/test/commons/table/get-headers.js index e7d44cd4c2..9bea2bc19e 100644 --- a/test/commons/table/get-headers.js +++ b/test/commons/table/get-headers.js @@ -107,6 +107,22 @@ describe('table.getHeaders', function() { ]); }); + it('should handle rowspan=0', function() { + fixture.innerHTML = + '' + + '' + + '' + + '
12
'; + + var target = $id('target'); + + axe.testUtils.flatTreeSetup(fixture.firstChild); + assert.deepEqual(axe.commons.table.getHeaders(target), [ + $id('t1'), + $id('t2') + ]); + }); + it('should handle headers attribute', function() { fixture.innerHTML = '' + diff --git a/test/commons/table/to-grid.js b/test/commons/table/to-grid.js index 18849b2e9e..38b78640f2 100644 --- a/test/commons/table/to-grid.js +++ b/test/commons/table/to-grid.js @@ -70,6 +70,21 @@ describe('table.toGrid', function() { ]); }); + it('should handle rowspan=0', function() { + fixture.innerHTML = + '
' + + '' + + '' + + '
2ok
45
'; + + var target = fixture.querySelector('table'); + + assert.deepEqual(axe.commons.table.toGrid(target), [ + [$id('t1'), $id('t2'), $id('t3')], + [$id('t4'), $id('t2'), $id('t5')] + ]); + }); + it('should insert an empty array for empty rows', function() { fixture.innerHTML = '' + '' + '' + '
ok
';