Accessibility question (screen readers)...

12 posts, 2 answers
  1. Raymond
    Raymond avatar
    20 posts
    Member since:
    Jul 2014

    Posted 08 Jun Link to this post

    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

     

  2. Alex Hajigeorgieva
    Admin
    Alex Hajigeorgieva avatar
    115 posts

    Posted 10 Jun Link to this post

    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.
  3. Kendo UI is VS 2017 Ready
  4. Raymond
    Raymond avatar
    20 posts
    Member since:
    Jul 2014

    Posted 10 Jun in reply to Alex Hajigeorgieva Link to this post

    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.

     

  5. Alex Hajigeorgieva
    Admin
    Alex Hajigeorgieva avatar
    115 posts

    Posted 14 Jun Link to this post

    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.
     
  6. Raymond
    Raymond avatar
    20 posts
    Member since:
    Jul 2014

    Posted 15 Jun Link to this post

    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.

  7. Alex Hajigeorgieva
    Admin
    Alex Hajigeorgieva avatar
    115 posts

    Posted 17 Jun Link to this post

    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.
     
  8. Raymond
    Raymond avatar
    20 posts
    Member since:
    Jul 2014

    Posted 12 Aug Link to this post

    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?

     

  9. Answer
    Alex Hajigeorgieva
    Admin
    Alex Hajigeorgieva avatar
    115 posts

    Posted 16 Aug Link to this post

    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. 
  10. Raymond
    Raymond avatar
    20 posts
    Member since:
    Jul 2014

    Posted 16 Aug in reply to Alex Hajigeorgieva Link to this post

    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>

     

  11. Raymond
    Raymond avatar
    20 posts
    Member since:
    Jul 2014

    Posted 16 Aug in reply to Alex Hajigeorgieva Link to this post

    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.
  12. Answer
    Alex Hajigeorgieva
    Admin
    Alex Hajigeorgieva avatar
    115 posts

    Posted 18 Aug Link to this post

    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
  13. Raymond
    Raymond avatar
    20 posts
    Member since:
    Jul 2014

    Posted 18 Aug in reply to Alex Hajigeorgieva Link to this post

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

     

    Thanks!

Back to Top
Kendo UI is VS 2017 Ready