This is a migrated thread and some comments may be shown as answers.

Accessibility question (screen readers)...

11 Answers 263 Views
Grid
This is a migrated thread and some comments may be shown as answers.
Raymond
Top achievements
Rank 1
Raymond asked on 08 Jun 2016, 03:57 PM

We are trying to make our applications compliant with the Web Content Accessibility Guidelines (WCAG) (https://www.w3.org/TR/WCAG20/).  One of the requirements is that buttons have text associated with them.  

When I created a grid (markup provided below), it fails WCAG compliance because the filter buttons in the column headers do not have text associated with them.  I found a way to add the text into the span using javascript but it seems like there should be a better way.  

Then I noticed that your demo grid (http://demos.telerik.com/kendo-ui/grid/filter-menu-customization) has the text property set.  If I inspect the markup for one of the filter buttons in your demo, I see this:  

<a class="k-grid-filter" href="#" tabindex="-1"><span class="k-icon k-filter">Filter</span></a>

So my question is...how did the text property of the span get the value "Filter"?  And how can I accomplish that in my grid defined as follows:

 

 

    @(Html.Kendo().Grid<Staff.Models.Employee>()

    .Name("grdEmployees")
    .Columns(columns =>
    {
        columns.Bound(p => p.FirstName).Width("9%").Title("First Name").Filterable(f => f.Extra(false).Operators(o => o.ForString(s => s.Clear().Contains("Contains").IsEqualTo("Is equal to").IsNotEqualTo("Is not equal to").StartsWith("Starts with").EndsWith("Ends with"))).Cell(cell => cell.Operator("Contains")));
        columns.Bound(p => p.LastName).Width("9%").Title("Last Name").Filterable(f => f.Extra(false).Operators(o => o.ForString(s => s.Clear().Contains("Contains").IsEqualTo("Is equal to").IsNotEqualTo("Is not equal to").StartsWith("Starts with").EndsWith("Ends with"))).Cell(cell => cell.Operator("Contains")));
        columns.Bound(p => p.OfficeDesc).Width("25%").Title("Office").MinScreenWidth(900).Filterable(f => f.Extra(false).Operators(o => o.ForString(s => s.Clear().Contains("Contains").IsEqualTo("Is equal to").IsNotEqualTo("Is not equal to").StartsWith("Starts with").EndsWith("Ends with"))).Cell(cell => cell.Operator("Contains")));
        columns.Bound(p => p.WorkUnitDesc).Width("15%").Title("Work Unit").Filterable(f => f.Extra(false).Operators(o=> o.ForString(s => s.Clear().Contains("Contains").IsEqualTo("Is equal to").IsNotEqualTo("Is not equal to").StartsWith("Starts with").EndsWith("Ends with"))).Cell(cell => cell.Operator("Contains"))).MinScreenWidth(900);
        columns.Bound(p => p.EMail).Width("18%").Title("Email").Filterable(f => f.Extra(false).Operators(o=> o.ForString(s => s.Clear().Contains("Contains").IsEqualTo("Is equal to").IsNotEqualTo("Is not equal to").StartsWith("Starts with").EndsWith("Ends with"))).Cell(cell => cell.Operator("Contains")));
        columns.Bound(p => p.Phone).Width("8%").Title("Phone").Filterable(f => f.Extra(false).Operators(o => o.ForString(s => s.Clear().Contains("Contains").IsEqualTo("Is equal to").IsNotEqualTo("Is not equal to").StartsWith("Starts with").EndsWith("Ends with"))).Cell(cell => cell.Operator("Contains")));
        columns.Bound(p => p.Title).Width("16%").Title("Title").Filterable(f => f.Extra(false).Operators(o=> o.ForString(s => s.Clear().Contains("Contains").IsEqualTo("Is equal to").IsNotEqualTo("Is not equal to").StartsWith("Starts with").EndsWith("Ends with"))).Cell(cell => cell.Operator("Contains"))).MinScreenWidth(900); 
    })
    .ClientRowTemplate(
        "<tr >" +
            "<td >#: FirstName# </td>" +
            "<td >#: LastName# </td>" +
            "<td >#: OfficeDesc #</td>" +
            "<td >#: WorkUnitDesc #</td>" +
            "<td ><a href='mailto:#: EMail #' title='Send Email' alt='Send Email' >#: EMail #</a></td>" +
            "<td style='white-space:nowrap;' >#: Phone #</td>" +
            "<td >#: Title #</td>" +
            "</tr>"
        )
    .ClientAltRowTemplate(
            @"<tr class=""alt-row"" >" +
            "<td >#: FirstName# </td>" +
            "<td >#: LastName# </td>" +
            "<td >#: OfficeDesc #</td>" +
            "<td >#: WorkUnitDesc #</td>" +
            "<td ><a href='mailto:#: EMail #'>#: EMail #</a></td>" +
            "<td style='white-space:nowrap;' >#: Phone #</td>" +
            "<td >#: Title #</td>" +
            "</tr>"
        )
    .Pageable()
    .Sortable()
    .Filterable()
    .DataSource(dataSource => dataSource
        .Ajax()
        .PageSize(20)
        .Read(read => read.Action("Staff_Read", "Staff"))
        .Filter(f => f.AddRange(ViewBag.filters))
    )
    )

Thanks,

 

Ray

 

11 Answers, 1 is accepted

Sort by
0
Alex Hajigeorgieva
Telerik team
answered on 10 Jun 2016, 02:34 PM

Hello Raymond,

The text in the <span> which holds the filter icon of the Kendo UI Grid is added out of the box since Kendo UI Q1 2016. 

To download the latest version of Kendo UI, go to:
https://www.telerik.com/account/my-downloads

Otherwise, to achieve the same behaviour, attach an event listener to the dataBound event of the Kendo UI Grid in one of the two ways below:

1.) With JavaScript:

$(document).ready(function(){
  var grid = $("#grid").data("kendoGrid");
  grid.bind("dataBound", function(){
    $('span.k-icon.k-filter').html('YourTitle')
 });
})

2.) With the GridEventBinder as part of the Kendo UI Grid configuration:
Documentation example is available just below the Remove event from the link below:

http://docs.telerik.com/kendo-ui/api/aspnet-mvc/Kendo.Mvc.UI.Fluent/GridEventBuilder#methods-Remove(System.String)

Let me know if you have any more questions regarding the Kendo UI Grid Configuration.

 

Kind Regards,
Alex
Telerik
Get started with Kendo UI in days. Online training courses help you quickly implement components into your apps.
0
Raymond
Top achievements
Rank 1
answered on 10 Jun 2016, 04:02 PM

Based on the version number of the Kendo.Mvc.dll in my project, I was running 2016.1.226.545.  Unless I'm mistaken, that is the Q1 2016 version.  However, I went ahead and allowed the upgrade wizard to run and now the kendo.Mvc.dll version is 2016.2.504.545. But I'm still getting the same behavior...no text in the span.

I was able to add the text using javascript and I'm glad to know how to modify it should the need arise.  But if including the text should be default behavior, I would much prefer to get that working rather than have to rely on a javascript workaround.  Are there any other troubleshooting steps I can try to see why neither the Q1 or Q2 2016 are including the text?

Clearly the grid is constructed on the client using a javascript library. Is there a way I can verify that library is up to date, independently of checking the dll version?

Thanks.

 

0
Alex Hajigeorgieva
Telerik team
answered on 14 Jun 2016, 02:43 PM
Hi Raymond,

Further investigation for the missing text in the <span class="k-icon k-filter"> in the UI for ASP.NET MVC Grid, led me to the answer. The newly supported functionality did not make it to the server wrappers in Kendo UI Q1 2016. I have logged the issue and you can track its progress here:

https://github.com/telerik/kendo-ui-core/issues/1793

As a token of gratitude, I have updated your Telerik points.

Kind Regards,
Alex
Telerik
 
Get started with Kendo UI in days. Online training courses help you quickly implement components into your apps.
 
0
Raymond
Top achievements
Rank 1
answered on 15 Jun 2016, 03:14 PM

Thanks for the update.  As part of this, can you also check to see if labels or equivalent are also applied to the filter popup?  Our accessibility evaluation tool is also complaining about the drop down for the filter ("contains", "starts with", etc) and the text box for the filter text.  I'm guessing that might already be included...but I thought I'd mention it.

 

Thanks.

0
Alex Hajigeorgieva
Telerik team
answered on 17 Jun 2016, 02:55 PM
Hello Raymond,

The issue was closed two days ago. The server wrappers will enable configuration for all the Kendo UI Grid Filter messages. The fix should be included in the Q3 2016 release.

Thank you for helping us improve.

Kind Regards,
Alex
Telerik
 
Get started with Kendo UI in days. Online training courses help you quickly implement components into your apps.
 
0
Raymond
Top achievements
Rank 1
answered on 12 Aug 2016, 08:56 PM

I'm now having kind of a similar issue applying attributes to the <a> tag that expands/collapses a detail grid.  The previous workaround used jquery to the document.ready event to apply attributes to the filter controls.  I tried the same approach using the following in the document ready function:

        var arr1 = $(".k-plus");
        for (var i = 0; i < arr1.length; i++) {
            arr1[i].setAttribute("title", "Expand");
            arr1[i].setAttribute("alt", "Expand");
            arr1[i].textContent = "Expand";
        }

The problem is that the rows containing the expand/collapse tag don't appear to be created until the asynchronous data call...which is well after the document ready function fires.

I've tried using similar code in the grid databind and change events, but it still appears to be before the data rows are rendered because it does not find the expand/collapse controls.  Is there a grid event that fires after all of the rows are rendered?

 

0
Accepted
Alex Hajigeorgieva
Telerik team
answered on 16 Aug 2016, 02:37 PM
Hi Raymond,

I would recommend using the Kendo UI Grid dataBound event to add the accessibility text to the expand icons. The Kendo UI Grid should have everything ready before it is triggered,thus my recommendation to use it.

I tested the code snippet provided and it works as required. The demo is available at:

http://dojo.telerik.com/OFoHI

Additionally, I can think of a way to provide better accessibility. You could toggle the text of the icon, i.e "Expand", "Collapse" dependent on the state of the detail. If you like the idea, you could take advantage of the detail collapse/expand events:

- detailExpand: http://docs.telerik.com/kendo-ui/api/javascript/ui/grid#events-detailExpand

- detailCollapse: http://docs.telerik.com/kendo-ui/api/javascript/ui/grid#events-detailCollapse

Let me know should you need further assistance.

Regards,
Alex
Telerik by Progress
 
Get started with Kendo UI in days. Online training courses help you quickly implement components into your apps. 
0
Raymond
Top achievements
Rank 1
answered on 16 Aug 2016, 03:28 PM

Ok...this is a little weird.  The code works correctly as an inline function.  But when the code is in a separate function, the find operator ($) returns an empty array.

This works...

    .Events(e => e.DataBound(@<text>function(e) {debugger;
        var arr1 = $(".k-plus");
        for (var i = 0; i < arr1.length; i++) {
            arr1[i].setAttribute("title", "Expand");
            arr1[i].setAttribute("alt", "Expand");
            arr1[i].textContent = "Expand";
        }}</text>))

 

But this does not because arr1 will have a length of zero...

    .Events(e => e.DataBound("ApplyReaderTags()"))

<script>

    function ApplyReaderTags() {
        var arr1 = $(".k-plus");
        for (var i = 0; i < arr1.length; i++) {
            arr1[i].setAttribute("title", "Expand");
            arr1[i].setAttribute("alt", "Expand");
            arr1[i].textContent = "Expand";
        }
    }
</script>

 

0
Raymond
Top achievements
Rank 1
answered on 16 Aug 2016, 03:35 PM
Ok...this is odd.  The javascript code works properly as inline code.  But it does not work as a separate javascript function.

When defining the event handler, this works...

    .Events(e => e.DataBound(@<text>function(e) {debugger;
        var arr1 = $(".k-plus");
        for (var i = 0; i < arr1.length; i++) {
            arr1[i].setAttribute("title", "Expand");
            arr1[i].setAttribute("alt", "Expand");
            arr1[i].textContent = "Expand";
        }}</text>))


But this does not...

    .Events(e => e.DataBound("ApplyReaderTags()"))


<script>
    function ApplyReaderTags() {

        var arr1 = $(".k-plus");

        for (var i = 0; i < arr1.length; i++) {
            arr1[i].setAttribute("title", "Expand");
            arr1[i].setAttribute("alt", "Expand");
            arr1[i].textContent = "Expand";
        }

    }
</script>

Debugging shows that when the code is a separate function, the find operator ($) returns an empty array so arr1 has a length of zero.
0
Accepted
Alex Hajigeorgieva
Telerik team
answered on 18 Aug 2016, 01:16 PM
Hi Raymond,

The correct syntax is:

.Events(e => e.DataBound("ApplyReaderTags"))

Documentation reference:

http://docs.telerik.com/kendo-ui/api/aspnet-mvc/Kendo.Mvc.UI.Fluent/GridEventBuilder#methods-DataBound(System.String)

Kind Regards,
Alex
Telerik by Progress
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
0
Raymond
Top achievements
Rank 1
answered on 18 Aug 2016, 03:05 PM

I thought I had tried that.  But it works so I must have had something else wrong. 

 

Thanks!

Tags
Grid
Asked by
Raymond
Top achievements
Rank 1
Answers by
Alex Hajigeorgieva
Telerik team
Raymond
Top achievements
Rank 1
Share this question
or