Skip to content

Commit

Permalink
Automate table standard, fixes #34
Browse files Browse the repository at this point in the history
  • Loading branch information
joshski committed Feb 20, 2017
1 parent 2f62081 commit dd925fa
Show file tree
Hide file tree
Showing 7 changed files with 601 additions and 1 deletion.
278 changes: 278 additions & 0 deletions features/check_standards/21_tables.feature
Original file line number Diff line number Diff line change
@@ -1 +1,279 @@
Feature: Tables

Data tables must be marked up in a way that enable browsers and assistive
technologies to identify them as such.

Rationale
=========

Assistive technologies such as screen readers identify HTML tables as being
either for data or for layout based on the markup used.

If a <table> is identified as a layout table then potentially useful
structures may be ignored.

Definitions
===========

Algorithm
---------

The following algorithm is used to determine if a <table> has been marked up
in a way that allows browsers and assistive technologies to identify it as a
data table:

* Table inside editable area is data table always since the table structure
is crucial for table editing

* Table having ARIA table related role is data table (like ARIA grid or
treegrid)

* Table having ARIA landmark role is data table

* Table having datatable="0" attribute is layout table

* Table created by CSS display style is layout table

* Table having summary attribute or legitimate data table structures is data
table; these structures are:

* <caption> element
* <col> or <colgroup> elements
* <tfoot> or <thead> elements
* <th> elements
* header, scope or abbr attributes on table cell
* abbr element as a single child element of table cell

* Table having nested table is layout table

* Table having only one row or column is layout table

* Table having many columns (>= 5) is data table

* Table having borders around cells is data table

* Table having differently colored rows is data table

* Table having many rows (>= 20) is data table

* Wide table (more than 95% of the document width) is layout table

* Table having small amount of cells (<= 10) is layout table
* Table containing <embed>, <object>, <applet> of iframe elements (typical
advertisements elements) is layout table

* Otherwise it’s data table

Go through each check in turn, stopping when you reach a data table or layout
table result.

Scenario: Data table
Given a page with the body:
"""
<table>
<tr>
<td>1</td><td>2</td><td>3</td><td>4</td><td>5</td><td>6</td>
</tr>
<tr>
<td>7</td><td>8</td><td>9</td><td>10</td><td>11</td><td>12</td>
</tr>
</table>
"""
When I validate the "Tables: Use tables for data" standard
Then it passes

Scenario: Table with datatable="0"
Given a page with the body:
"""
<table datatable="0">
<tr>
<td>1</td><td>2</td><td>3</td><td>4</td><td>5</td><td>6</td>
</tr>
<tr>
<td>1</td><td>2</td><td>3</td><td>4</td><td>5</td><td>6</td>
</tr>
</table>
"""
When I validate the "Tables: Use tables for data" standard
Then it fails with the message:
"""
Table used for layout: /html/body/table
"""

Scenario: Table created by CSS display style
Given a page with the body:
"""
<div style="display:table">
This isn't a table, it's just made to look like one
</div>
"""
When I validate the "Tables: Use tables for data" standard
Then it fails with the message:
"""
Table used for layout: /html/body/div
"""

Scenario: Nested table
Given a page with the body:
"""
<table>
<tr>
<td>1</td><td>2</td><td>3</td><td>4</td><td>5</td><td>6</td>
</tr>
<tr>
<td>1</td><td>2</td><td>3</td><td>4</td><td>5</td><td>6</td>
</tr>
<tr>
<td>
<table>
<tr>
<td>1</td><td>2</td><td>3</td><td>4</td><td>5</td><td>6</td>
</tr>
<tr>
<td>1</td><td>2</td><td>3</td><td>4</td><td>5</td><td>6</td>
</tr>
</table>
</td>
</tr>
</table>
"""
When I validate the "Tables: Use tables for data" standard
Then it fails with the message:
"""
Table used for layout: /html/body/table
"""

Scenario: Table with only one row and less than 5 columns
Given a page with the body:
"""
<table>
<tr>
<td>1</td><td>2</td><td>3</td><td>4</td>
</tr>
</table>
"""
When I validate the "Tables: Use tables for data" standard
Then it fails with the message:
"""
Table used for layout: /html/body/table
"""

Scenario: Table with only one column
Given a page with the body:
"""
<table>
<tr><td>1</td></tr>
<tr><td>2</td></tr>
<tr><td>3</td></tr>
<tr><td>4</td></tr>
<tr><td>5</td></tr>
<tr><td>6</td></tr>
<tr><td>7</td></tr>
<tr><td>8</td></tr>
<tr><td>9</td></tr>
<tr><td>10</td></tr>
<tr><td>11</td></tr>
<tr><td>12</td></tr>
<tr><td>13</td></tr>
<tr><td>14</td></tr>
<tr><td>15</td></tr>
<tr><td>16</td></tr>
<tr><td>17</td></tr>
<tr><td>18</td></tr>
<tr><td>19</td></tr>
</table>
"""
When I validate the "Tables: Use tables for data" standard
Then it fails with the message:
"""
Table used for layout: /html/body/table
"""

Scenario: Wide table
Given a page with the body:
"""
<!-- 110% to account for body padding -->
<table style="width:110%">
<tr>
<td>1</td><td>2</td><td>3</td><td>4</td>
</tr>
<tr>
<td>1</td><td>2</td><td>3</td><td>4</td>
</tr>
<tr>
<td>1</td><td>2</td><td>3</td><td>4</td>
</tr>
</table>
"""
When I validate the "Tables: Use tables for data" standard
Then it fails with the message:
"""
Table used for layout: /html/body/table
"""

Scenario: Table with few cells
Given a page with the body:
"""
<table>
<tr>
<td>1</td><td>2</td><td>3</td>
</tr>
<tr>
<td>4</td><td>5</td><td>6</td>
</tr>
<tr>
<td>7</td><td>8</td><td>9</td>
</tr>
</table>
"""
When I validate the "Tables: Use tables for data" standard
Then it fails with the message:
"""
Table used for layout: /html/body/table
"""

Scenario: Tables with advertising elements
Given a page with the body:
"""
<table>
<tr>
<td>1</td><td>2</td><td>3</td><td>4</td>
</tr>
<tr>
<td>5</td><td>6</td><td>7</td><td>8</td>
</tr>
<tr>
<td>9</td><td>10</td><td>11</td><td><object /></td>
</tr>
</table>
<table>
<tr>
<td>1</td><td>2</td><td>3</td><td>4</td>
</tr>
<tr>
<td>5</td><td>6</td><td>7</td><td>8</td>
</tr>
<tr>
<td>9</td><td>10</td><td>11</td><td><embed /></td>
</tr>
</table>
<table>
<tr>
<td>1</td><td>2</td><td>3</td><td>4</td>
</tr>
<tr>
<td>5</td><td>6</td><td>7</td><td>8</td>
</tr>
<tr>
<td>9</td><td>10</td><td>11</td><td><applet /></td>
</tr>
</table>
"""
When I validate the "Tables: Use tables for data" standard
Then it fails with the message:
"""
Table used for layout: /html/body/table[1]
Table used for layout: /html/body/table[2]
Table used for layout: /html/body/table[3]
"""
16 changes: 16 additions & 0 deletions features/cli/json_reporter.feature
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,14 @@ Feature: JSON Reporter
"errors": [],
"hiddenErrors": []
},
{
"standard": {
"section": "Tables",
"name": "Use tables for data"
},
"errors": [],
"hiddenErrors": []
},
{
"standard": {
"section": "Title attributes",
Expand Down Expand Up @@ -231,6 +239,14 @@ Feature: JSON Reporter
"errors": [],
"hiddenErrors": []
},
{
"standard": {
"section": "Tables",
"name": "Use tables for data"
},
"errors": [],
"hiddenErrors": []
},
{
"standard": {
"section": "Title attributes",
Expand Down
2 changes: 1 addition & 1 deletion features/step_definitions/a11y_steps.js
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ defineSupportCode(function({ Given, When, Then }) {
}).join(" ")
}).join("\n");
}).join("\n")
assert.equal(message, actualMessage)
assert.equal(actualMessage, message)
})

Then('the exit status should be {status:int}', function (status) {
Expand Down
48 changes: 48 additions & 0 deletions lib/detectTableType.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
var $ = require('jquery')

function detectTableType(table) {
var $table = $(table)
if ($table.is(':not(table),[datatable=0]')) {
return 'layout'
}

if ($table.parents("[contenteditable=true]").length > 0 ||
$table.is('[role=grid],[role=treegrid],[role=landmark],[summary],:has(caption,col,colgroup,tfoot,thead,th,td[header],td[scope],td[abbr],td:has(>abbr:only-child))')) {
return 'data'
}

if ($table.is(':has(table)')) {
return 'layout'
}

var cells = $table.find('> tr > td, > tbody > tr > td')
var rows = $table.find('> tr, > tbody > tr')
var cols = Math.max.apply(null, rows.get().map(function(row) { return $(row).find('> td').length }))

if (cols >= 5 || rows.length >= 20 || cells.get().some(function(cell) { return $(cell).css('border-width') != '0px' })) {
return 'data'
}

if (rows.length == 1 || cols == 1) {
return 'layout'
}

var tableWidth = $(table).width()
var documentWidth = $(table.ownerDocument).width()
var percentOfDocumentWidth = (tableWidth / documentWidth) * 100
if (percentOfDocumentWidth > 95) {
return 'layout'
}

if (cells.length <= 10) {
return 'layout'
}

if ($table.is(':has(object,embed,applet)')) {
return 'layout'
}

return 'data'
}

module.exports = detectTableType
8 changes: 8 additions & 0 deletions lib/standards/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,14 @@ Standards.sections = {
documentationUrl: 'http://www.bbc.co.uk/guidelines/futuremedia/accessibility/html/tabindex.shtml'
},

tables: {
title: 'Tables',
tests: [
require('./tables/useTablesForData')
],
documentationUrl: 'http://www.bbc.co.uk/guidelines/futuremedia/accessibility/html/tables.shtml'
},

titleAttributes: {
title: 'Title attributes',
tests: [
Expand Down
Loading

0 comments on commit dd925fa

Please sign in to comment.