On a code review i found - the XHTML will not validate with XHTML 1.0 Transitional or higher.
Line [189] has missing $attributes:
$output = theme('table', $header, $items);
maybe other doctypes requires more options, please test with XHTML 1.1, XHTML 1.1 Strict, XHTML 2.0, etc.
Comments
Comment #1
merlinofchaos commentedNone of Drupal's tables have a summary attribute. I don't feel a need to conform to a standard that the rest of Drupal doesn't conform to.
Comment #2
marc.bauso, please read http://drupal.org/node/44661. As you may find out:
so - your code does not fullfill guidelines for accessibility compliance and web standard compliance! please fix this minor thing and keep the world a little bit more accessible for handicaped people. It's not a big trick and you will not break anything. Simply do this minor change for example:
Thank you.
Comment #3
marc.bauHave you read the article? Are you able to fix this bug, please? i realy don't like to offer a forked version of panels for download.
Comment #4
merlinofchaos commentedWhen Drupal core puts summary attributes in tables, I will.
Until then, I'm not going to bother with standards that core doesn't either. Nobody gets anything.
Comment #5
marc.baucore does not have this bugs. i don't know why you reference core. have you read the article??? it is seen as a bug.
Comment #6
merlinofchaos commentedA quick grep from drupal core shows roughly 40 instances of theme('table', $header, $rows) with no attributes whatsoever.
There are NO SUMMARY attributes in those. Anywhere. The only 'summary' I can find is on a manually created table in the aggregator module.
Now please, stop wasting my time with this. I have far better things to do.
Comment #7
wdmartin commentedPosting a workaround for the future reference of anyone who does in fact want summary attributes on these tables.
It is possible to assign summary attributes to event tables by overriding the four themable functions in event.theme that generate tables. The four functions are:
Copy each of these to your theme's template.php file (which you can create if it doesn't exist), and replace "theme" with the name of your theme. The theme-specific functions will be used in preference to the generic functions. Then you can add summary attributes as in the first post in this thread.
Do not modify event.theme directly, as your changes will then get overwritten the next time you upgrade the module to a newer version. Putting overrides in your template.php file means that your modifications will continue to function as you update to newer versions of the module and Drupal itself. In the event that you need to override multiple themes, recall that using "phptemplate" instead of your theme's name will make the modified function compatible with any theme written in PHPTemplate. In my case, I have some 47 themes to maintain, so I have a universal_overrides.php file containing accessibility overrides like this one, which I then include() in each template.php file so that my fixes will apply instantly to all the themes.
Lastly, I should point out that summary attributes are a Good Thing for those using screen readers, and may also be a legal requirement. They're certainly needed for Section 508 compliance, which is mandated for publicly funded web sites in the U.S., including those maintained by public schools and universities. However, adding them directly to the event module would raise problems with internationalization. It's much better to handle this at the theme level.
Comment #8
wdmartin commentedCrud, I used an event.module example when this bug was filed against panels. Sorry. But the basic principle is sound - just identify the relevant themable functions and override them.
Comment #9
mgiffordThis is a rather old post, but not sure how much has changed (other than general attitudes about accessibility) since this issue was added in 2006. @merlinofchaos needless to say Panels has improved so very, very much since this time. Heck, this may no longer be an issue, however I can't see a reference for the use of a summary field if I grep for summary:
$ grep -ir summary drupal6/sites/all/modules/panels/*
Ok, so it is possible to add a summary table using theme_table():
http://api.drupal.org/api/function/theme_table
as this function can accept attributes through $variables. E.g. $variables['attributes']['summary'] = t('example summary')
So there are still no summary tables used in core:
$ grep -ir attributes drupal7/* | grep summary
$ grep -ir "theme('table" drupal7/* | grep summary
Mind you it looks like there are still lots of places where they should be suggested.
includes/locale.inc: $output .= theme('table', array('header' => $header, 'rows' => $rows, 'empty' => t('No strings available.'))); modules/field_ui/field_ui.admin.inc: $output = theme('table', array('header' => $header, 'rows' => $rows)); modules/user/user.admin.inc: $output .= theme('table', array('header' => $header, 'rows' => $rows, 'attributes' => array('id' => 'permissions'))); modules/user/user.admin.inc: $output = theme('table', array('header' => $header, 'rows' => $rows, 'attributes' => array('id' => 'user-roles'))); modules/simpletest/tests/theme.test: $this->content = theme('table', array('header' => $header, 'rows' => $rows)); modules/simpletest/tests/theme.test: $this->content = theme('table', array('header' => $header, 'rows' => $rows, 'attributes' => $attributes, 'caption' => $caption, 'colgroups' => $colgroups, 'sticky' => FALSE)); modules/simpletest/tests/theme.test: $this->content = theme('table', array('header' => $header, 'rows' => array(), 'empty' => t('No strings available.'))); modules/simpletest/simpletest.pages.inc: theme('table_select_header_cell'), modules/simpletest/simpletest.pages.inc: return theme('table', array('header' => $header, 'rows' => $rows, 'attributes' => array('id' => 'simpletest-form-table'))); modules/shortcut/shortcut.admin.inc: return theme('table', array('header' => $header, 'rows' => $rows)); modules/shortcut/shortcut.admin.inc: $output = theme('table', array('header' => $header, 'rows' => $rows, 'attributes' => array('id' => 'shortcuts'))); modules/trigger/trigger.admin.inc: $output = theme('table', array('header' => $header, 'rows' => $rows)) . drupal_render_children($element); modules/field/field.form.inc: $output .= theme('table', array('header' => $header, 'rows' => $rows, 'attributes' => array('id' => $table_id, 'class' => array('field-multiple-table')))); modules/book/book.admin.inc: return theme('table', array('header' => $headers, 'rows' => $rows, 'empty' => t('No books available.'))); modules/book/book.admin.inc: return theme('table', array('header' => $header, 'rows' => $rows, 'attributes' => array('id' => 'book-outline'))); modules/filter/filter.admin.inc: $output = theme('table', array('header' => $header, 'rows' => $rows, 'attributes' => array('id' => 'text-format-order'))); modules/filter/filter.admin.inc: $output .= theme('table', array('rows' => $rows, 'attributes' => array('id' => 'filter-order'))); modules/filter/filter.module: $output .= theme('table', array('header' => $header, 'rows' => $rows)); modules/filter/filter.module: $output .= theme('table', array('header' => $header, 'rows' => $rows)); modules/menu/menu.admin.inc: return theme('table', array('header' => $header, 'rows' => $rows)); modules/menu/menu.admin.inc: $output .= theme('table', array('header' => $header, 'rows' => $rows, 'attributes' => array('id' => 'menu-overview'))); modules/update/update.manager.inc: '#markup' => theme('table', array('header' => $headers, 'rows' => $projects['manual'])), modules/update/update.report.inc: $output .= theme('table', array('header' => $header, 'rows' => $rows[$type_name], 'attributes' => array('class' => array('update')))); modules/taxonomy/taxonomy.admin.inc: return theme('table', array('header' => $header, 'rows' => $rows, 'empty' => t('No vocabularies available. Add vocabulary.', array('@link' => url('admin/structure/taxonomy/add'))), 'attributes' => array('id' => 'taxonomy'))) . drupal_render_children($form); modules/taxonomy/taxonomy.admin.inc: $output = theme('table', array('header' => $header, 'rows' => $rows, 'attributes' => array('id' => 'taxonomy'))); modules/aggregator/aggregator.admin.inc: $output .= theme('table', array('header' => $header, 'rows' => $rows, 'empty' => t('No feeds available. Add feed.', array('@link' => url('admin/config/services/aggregator/add/feed'))))); modules/aggregator/aggregator.admin.inc: $output .= theme('table', array('header' => $header, 'rows' => $rows, 'empty' => t('No categories available. Add category.', array('@link' => url('admin/config/services/aggregator/add/category'))))); modules/aggregator/aggregator.pages.inc: $output .= theme('table', array('header' => array('', t('Categorize')), 'rows' => $rows)); modules/profile/profile.admin.inc: $output = theme('table', array('header' => $header, 'rows' => $rows, 'empty' => t('No fields available.'), 'attributes' => array('id' => 'profile-fields'))); modules/poll/poll.module: $output = theme('table', array('header' => $headers, 'rows' => $rows, 'attributes' => array('id' => 'poll-choice-table'))); modules/image/image.admin.inc: return theme('table', array('header' => $header, 'rows' => $rows)); modules/image/image.admin.inc: $output = theme('table', array('header' => $header, 'rows' => $rows, 'attributes' => array('id' => 'image-style-effects'))); modules/image/image.admin.inc: return theme('table', array('header' => array(), 'rows' => $rows, 'attributes' => array('class' => array('image-anchor')))); modules/locale/locale.admin.inc: $output = theme('table', array('header' => $header, 'rows' => $rows, 'attributes' => array('id' => 'language-order'))); modules/locale/locale.admin.inc: $table = theme('table', $variables); modules/locale/locale.admin.inc: return theme('table', array('header' => $headers, 'rows' => $rows)); modules/locale/locale.admin.inc: $output .= theme('table', array('header' => $header, 'rows' => $rows)); modules/locale/locale.admin.inc: return theme('table', array('header' => $header, 'rows' => $rows)); modules/file/file.field.inc: $output = empty($rows) ? '' : theme('table', array('header' => $headers, 'rows' => $rows, 'attributes' => array('id' => $table_id))); modules/file/file.field.inc: return empty($rows) ? '' : theme('table', array('header' => $header, 'rows' => $rows)); modules/node/node.module: $output .= theme('table', array('header' => $header, 'rows' => $rows)); modules/node/node.module: $output = theme('table', array('rows' => $rows)); modules/block/block.js: return ''; modules/system/theme.api.php: * theme('table', array('header' => $header, 'rows' => $rows)); modules/system/system.admin.inc: $output = theme('table', array('header' => $header, 'rows' => $rows, 'attributes' => array('id' => 'system-date-types'))); modules/system/system.admin.inc: return theme('table', array('header' => $form['#header'], 'rows' => $rows)); modules/system/system.admin.inc: $output = theme('table', array('header' => $header, 'rows' => $rows, 'empty' => t('No modules are available to uninstall.'))); modules/system/system.admin.inc: $build['system_actions_table'] = array('#markup' => theme('table', array('header' => $header, 'rows' => $row)));So there are a few places here to look for and add summary tables in D7 core. I guess I'll file a few patches.
Mike
Comment #10
mgiffordadding accessibility tag.
Comment #11
mgiffordforgot to change the version number too.
Comment #12
Letharion commentedI'm all for AX, but after looking at the Core queue, merlins initial response seems to stand. And while it would be nice for Panels to go "above and beyond", this seems like a relatively low priority target. The issue can definitely be opened again for discussion, but after a year and a half of silence, and not much work seemingly going into core, I will now close this issue again.