Can I enhance complex table accessibility with JavaScript? - javascript

A website has a great number of complex informational tables with multi-level headers, a simple version of which is:
table { border: 1px solid black; border-collapse:collapse; width: 100%; }
td, th { border: 1px solid black; }
th { background-color: lightgray; }
<!-- simplified table -->
<table>
<thead>
<tr><th></th><th>Col 1</th><th>Col 2</th></tr>
</thead>
<tbody>
<tr><th>Row 1</th><td>Foo</td><td>Bar</td></tr>
<tr><th colspan="3">Header for subregion</th></tr>
<tr><th>Row 2</th><td>Foo</td><td>Bar</td></tr>
<tr><th>Row 3</th><td>Foo</td><td>Bar</td></tr>
</tbody>
</table>
For various reasons, server-side and hand-coded solutions are out. If I use JavaScript that applies the suggested WAI fixes ("use id and headers attributes to associate header and data cells explicitly") to enhance the HTML, will this be reliably reflected in what users actually get in a screen reader?
Using ARIA Live Regions seems like it would needlessly update them to a host of changes. So, ideally, can it work without that?

The short answer is "yes". In general(*), any attributes you apply via javascript, whether ARIA attributes or any other html attributes, will be available to screen readers.
(*) There is (at least) one exception that I'm aware of, aria-live. There are browser and screen reader combinations where that attribute has to exist on the element when the page is loaded in order for it to be honored. You mentioned aria-live in your question but that attribute doesn't really come into play unless you are making updates to your page dyanamically (for example, if you table headers changed based on some user action).
I was going to show some sample code to show the desired results based on your code snippet, but your example is a little confusing. You have a "Header for subregion" that spans all the columns. Visually, it looks more like a caption/summary for the table than it does a column header. Can you clarify? Table captions should not be coded as headers (<th>).
Do you want "Header for subregion" to be read as the column header for every cell?

Related

I want to split a long HTML table row into multiple rows according to the page width

I am using AngularJS to generate a row of Material buttons in an HTML table. The selected button is highlighted.
<tr>
<td ng-click="pbmain.selectWC(WC.WCName)" ng-repeat="WC in pbmain.WCList">
md-button(ng-class="WC.WCName == pbmain.selectedWCName ? 'md-raised md-primary' : 'md-raised'") {{WC.WCName}}
</td>
</tr>
The number of buttons and text on the buttons can be quite long and the row is often 2-3 times the width of the browser window. For the moment, I scroll across but I am looking for a more user-friendly solution.
I would like to be able to split the row automatically, according to the page width - something like the example below.
You can achieve this by applying proper CSS to table and button elements. No need to split a row into multiple rows.
Example:
<table border="0" cellspacing="0" cellpadding="0">
<tr>
<td>
<span>TEST</span><span>TEST</span><span>TEST</span><span>TEST</span><span>TEST</span><span>TEST</span><span>TEST</span><span>TEST</span><span>TEST</span><span>TEST</span><span>TEST</span><span>TEST</span><span>TEST</span><span>TEST</span><span>TEST</span><span>TEST</span><span>TEST</span><span>TEST</span><span>TEST</span><span>TEST</span><span>TEST</span><span>TEST</span><span>TEST</span><span>TEST</span><span>TEST</span><span>TEST</span><span>TEST</span><span>TEST</span><span>TEST</span><span>TEST</span><span>TEST</span><span>TEST</span>
</td>
</tr>
CSS
table {
table-layout: fixed;
width: 100%
}
span {
border: 1px solid black;
margin: 10px;
width: 100px;
display: inline-block;
}
Have a look at this fiddle.
Well, I was searching by splitting rows into multiple rows and I got here.
It seems that your problem could be better solver by using display: inline-block; for every button.
However, if you really need a table for other purpose check at this next approach.
It would redrawn your linear tabular long table into a multilined table by only using css.
Than you can play around with your screen size.
I have no idea how to accomplish this easily within a table. Maybe you could make some pre-work on your array to make it two-dimensional and then ng-repeat tr and td tags as well.
My solution would be a clean grid system with Bootstrap.
With this you can achieve a fully responsive screen. If you do not need to stick with a table system, then you should consider this.

Alternate to table to display data?

I am trying to display a table in HTML but it seems the table is unable to meet the specs. I would like to data to be in the same place on the screen otherwise it will cause all kinds of problems with the users as they mis-read the data. So I need fixed width columns. I also would like the column headers to remian fixed if the data exceeds the height of the windows because some users do use them.
I do not want to install any 3rd party controls if possible. The owner will not buy anything anyway. I don't mind something that downloads with the page.
I was thinking of trying to make a scrollable div with textboxes or labels but thought I should check to see if someone has already run into this issue and came up with a solution.
I asked here: How to make a scrolling table with dynamic data
but no one has a clue as to whats wrong.
Then I asked here: How to get a table to fit its parent container?
And the key here seems the column widths. But without the widths using the table seems pointless.
Asking this: Why don't my column headings line up?
Seems also to indicate that a table will never work.
Setting this:
display: table-row-group
Makes the column headings line up, but then the table can not scroll.
display: block
Makes the table scroll but the column headings are wrong.
Here's an example that works on its own. http://jsfiddle.net/kjzcv9g2/
<style type="text/css" media="screen">
table, th, td {border: solid;}
thead {
display: block;
color: #f00;
background: #eee;
height: 35px;
overflow-y: scroll;
}
tbody {
display: block;
height: 100px;
overflow-y: scroll;
}
th, td {
width: 10em;
font-weight: normal;
}
</style>
<table>
<thead>
<tr>
<th>foo</th>
<th>bar</th>
</tr>
</thead>
<tbody>
<tr>
<td>foo</td>
<td>bar</td>
</tr>
</tbody>
</table>
But getting this to work seems impossible.
Any suggestions on whether to use labels or textboxes to create my own table?
JSFIDDLE
If I understand the question correctly the above should work. Add a min-width to the overall table and you'll have fixed width columns below the min width, and the columns will fill the container about the min width.

Table sorter width 100% does not work if table is contained into others tables

I use tablesorter (https://github.com/Mottie/tablesorter), with widget scroller.
You can find examples here : http://mottie.github.io/tablesorter/docs/example-widget-scroller.html
My problem is when tablesorter is contained into other tables like
<table>
<tr>
<td>
table sorter table
</td>
</tr>
</table>
table sorter does not take 100% of the width... And the horizontal scrollbar does not appear automatically.
You can find a example here : http://jsfiddle.net/oqfq47fc/8/
Whereas if table sorter is not contained in other table, its works...
You can find a example here : http://jsfiddle.net/oqfq47fc/9/
Can you help me? I works in portal context and contents portlets are inside table, and it is not possible to remove nested tables.
I think it's just a matter of css, but I know no more...
EDIT
I need that table takes 100% of width like this picture :
And when I resize the browser and that the all table can not display in the available space, a horizontal scrollbar appear at the bottom of the table like this picture :
It works good in my first example.
But in my second example with the outer table, the table look like this picture :
And when I resize the browser, the horizontal scroll bar does not appear on table but on window like this picture :
table{
display: block;
max-width: 100%;
overflow-y: hidden;
overflow-x: scroll;
width: 100%;
}
table.data-table,table#tvar_1{
display: table;
}
html{
overflow-x: hidden;
}
.tablesorter-scroller-table{
width: 100% !important;
}
Fiddle
Adding this set of code is as close as I can get to reproducing what you want with strictly tables. You are using tables for layout and you really shouldn't be doing that. The best way to go is to use the div the way you are in the second iteration where it is correct. It obviously displays the correct and best way. Also, with what I had to do to these tables it is not nice.
Do your best to avoid tables where tables are not needed. This is tabular data so it is needed, but using a table to construct the page is not the right way to go.

Best way to create link inside td with onMouseOver function?

I have a table which includes a td with an onMouseOver function that changes the background color of the td. The text inside the td is a link. The problem I am having is that the link appears "highlighted" when the mouse hovers over the td, but can't be clicked on unless the mouse is hovering over the link itself. In other words, there is kind of a "buffer" zone around the link text but inside the boundaries of the td where the background color is changed but the cursor remains the standard pointer (and the link cannot be clicked). Is there a way to cause the entire td to be a link, or would I have to use two different images to get the desired effect?
Example code:
<table>
<tr>
<td onMouseOver="bgColChange();" style="background-color:#ffffff;">
Location 1
</td>
</tr>
</table>
You can do something like this:
<table>
<tr>
<td class="myTD0" onMouseOver="bgColChange();" style="background-color:red;cursor:pointer;" onClick="document.getElementById('myLink0').click();">
Location 1
</td>
</tr>
</table>
See I have added onClick on td with id of anchor tag
onclick="document.getElementById('myLink0').click();"
Demo Fiddle
I guess this is what you are looking for.
From what I understand, you want a TD element with a link inside of it and you want to:
change BG color when hovered
make entire TD element clickable for the link
The first thing to note is you're using inline JavaScript. That means you're placing raw JavaScript code inside your HTML. That is not a good practice or convention to follow. In the last several years the JavaScript community has stepped away from inline JavaScript.
Instead, the better approach is called "unobtrusive JavaScript" which is a fancy name that means you give your HTML elements class/ID names that you can reference in your JavaScript and CSS files.
This Wikipedia Article on Unobtrusive JavaScript is pretty good at showing what the differences are. The takeaway is that unobtrusive JavaScript is the preferred practice and should be used as much as possible.
I know there are unique situations where inline JS is still necessary, but you're particular problem doesn't need any JavaScript. You simply need to use some specific CSS. Often times the best solution is the simplest.
# HTMl file
# ----------------------------------------
<table class="custom">
<tr>
<td>
Location 1
</td>
</tr>
</table>
# CSS file
# # ----------------------------------------
.custom {
width: 100%;
}
/* Give TD element padding so you can see that link expands properly */
.custom td {
border: 1px solid black; /* For visual aid */
padding: 10px;
}
/* Change background color on hover of TD element */
.custom td:hover {
background: #ccc;
}
/* Change link color when hovering over TD element */
.custom td:hover a {
color: #fff;
}
/* Make link expand to entire TD element (its parent) */
.custom td a {
display: block;
text-decoration: none;
}
Here is a JS Fiddle example that works without using any JavaScript.
This solution is preferred because it does not use JavaScript and is much easier to understand as another developer.
You only need to add a custom class to your TABLE element so that you can attach CSS styles to it. I've added several comments in the JS Fiddle so be sure to check them out. You can also play with the JS Fiddle example to help you understand it further.

Enabling vertical scroll on HTML tables

I'm creating a table and populating it using javascript. I want to add a vertical scroll bar to the table, but on the data only, i.e. I want the table header to remain fixed, i.e. not be included in the scroll.
I want to use only javascript, CSS and valid HTML5 elements. At this stage I want to exclude jQuery. There have been many discussions on this topic, usually including horizontal scroll bars. I'm only interested in vertical scrolling and to me it is essential that the header columns must be aligned with the table data when scrolled. The discussions and my attempts to achieve this, lead me to believe this is impossible. If this is not the case can someone tell me how this is done?
So far I have made a number of attempts. Adding
table {
display: block;
height: 300px;
overflow: scroll;
}
causes vertical scrolling of the whole table, including the header and data, but the headers and data are aligned. Adding
thead {
display: block;
}
tbody {
display: block;
height: 300px;
overflow: scroll;
}
results in the header not scrolling, but the headers and data columns are no longer aligned. What appears to be happening is that the width of the header columns no longer takes account of the data columns.
I've tried numerous other approaches without success. I've had partial success by adding the same width value to header and data field columns based on the maximum field size, in characters, of the header and data values. With this approach I can get the header to align with the data for most columns. However, I don't regard this as an adequate solution, as it is in general not possible, or at least very difficult, to determine a value in em, px or mm, that will hold n characters exactly.
In the discussions I've seen, it seems that what I want to achieve is possible using jQuery. I've not yet embraced jQuery, but if it can easily enable what I want, it may be the time to do so. Can anyone confirm if what I want is possible in jQuery?
I find it hard to believe that what I want to do is not easily possible, as I would regard it as essential for any adequate handling of tables.
Maybe not the answer you're looking for, but a rather simple solution would be to put all the scrollable rows and columns within a scrollable div, and keep the headers and footers outside that div.
If you are willing to set your columns at a fixed width, you can basically make two tables - one for the header and one for the body, and then just set scrolling on the body.
HTML:
<table class="header">
<thead>
<td>Header</td><td>Header</td><td>Header</td>
</thead>
</table>
<table class="body">
<tbody>
<tr><td>data</td><td>data</td><td>data</td></tr>
...
</tbody>
</table>
And your css:
td, th{
width:50px;
}
table.body{
display: block;
height: 300px;
width:200px;
overflow: scroll;
}
See this jsFiddle.

Categories