阿里云新用户优惠

十七、UI-Grid Accessibility 无障碍性

原文:122 Accessibility

无障碍性 (或 A11Y) 通常是 web 开发中被忽略的方面。确保您的内容是可访问的, 类似于确保您的内容在所有主要浏览器上都可见。如果您在设计网站时不考虑辅助功能, 则您的内容将无法供所有用户使用。

先决条件:

  • 引入 angular-aria (Angular 1.3.0+)
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.16/angular.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular-aria.js"></script>
<link rel="styleSheet" href="release/ui-grid-unstable.css"/>
<script src="/release/ui-grid-unstable.js"></script>
  • 在app中依赖注入 ngAria
var app = angular.module('app', ['ngAria', 'ui.grid']);

浏览器支持状态

浏览器 操作系统 应用程序 核心 分页 单元格导航
Chrome OSX Voice Over 全部支持 全部支持 不一致的读取单元格导航。
Firefox OSX Voice Over 仅页眉/菜单 全部支持 没有,不能读取。
Safari OSX Voice Over 全部支持 全部支持 全部支持

为什么只有 osx?因为它是表格测试的唯一工具。如果你用其他东西来测试过它,可以随时更新这份文件。

用 OSX 的声音测试 可以通过⌘+F5来开启声音测试。设置修改声音自动跟随鼠标,将使声音控制光标移动到要开始导航的位置更容易。或者, 您也可以使用声音导航到表,在表格中管理焦点,以便在添加和移除菜单以及禁用按钮时,声音的光标保持不变。

测试没有 OSX 的声音 只需使用 tab 和 shift + tab 键即可在网格上导航菜单和按钮。

可视化辅助功能 您可以使用这个简单的 javascript 可视化小工具应用到表格的辅助功能:http://khan.github.io/tota11y/

  • index.html
<!doctype html>
<html ng-app="app">
  <head>
    <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.5.0/angular.js"></script>
    <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.5.0/angular-touch.js"></script>
    <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.5.0/angular-animate.js"></script>
    <script src="http://ui-grid.info/docs/grunt-scripts/csv.js"></script>
    <script src="http://ui-grid.info/docs/grunt-scripts/pdfmake.js"></script>
    <script src="http://ui-grid.info/docs/grunt-scripts/vfs_fonts.js"></script>
    <script src="http://ui-grid.info/release/ui-grid.js"></script>
    <script src="http://ui-grid.info/release/ui-grid.css"></script>
    <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.3.16/angular-aria.js"></script>
    <script src="app.js"></script>
  </head>
  <body>
    <div role="application" ng-controller="MainCtrl">
      <h3 id="example_short-dataset-without-virtualization">Short Dataset without Virtualization</h3>
      <button type="button" name="Set focus button" class="btn btn-default">Set Focus Here</button></br></br>
      <div id="grid1" ui-grid="smallGrid" class="grid1"></div>
      </br>
      <h3 id="example_long-dataset-with-virtualization">Long Dataset with Virtualization</h3>
      <button type="button" name="Set focus button" class="btn btn-default">Set Focus Here</button></br></br>
      <div id="grid2" ui-grid="virtualGridOptions" ui-grid-cellnav class="grid2" aria-labelledby="grid2-label"></div>
      <label id="grid2-label">A large list of people and the companies they work for.</label>
      <p>
        The above example only allows the screen reader to read the data that is currently visible.
        Since the browser has no knowledge about the location of the screen reader cursor the grid
        never scrolls.
        The plan for the future is to integrate cell nav with the aria labels so that the screen
        reader dictates where the user is on the grid.
      </p>
      </br>
      <h3 id="example_long-dataset-with-virtualization-and-pagination">Long Dataset with Virtualization and Pagination</h3>
      <button type="button" name="Set focus button" class="btn btn-default">Set Focus Here</button></br></br>
      <div id="grid3" ui-grid="paginationGridOptions" class="grid3" ui-grid-pagination aria-labelledby="grid3-label"></div>
      <label id="grid3-label">A large list of people and the companies they work for using pagination controls.</label>
    </div>
  </body>
</html>
  • main.css
.grid1 {
  width: 700px;
  height: 300px;
}
.grid2 {
  width: 700px;
  height: 400px;
}
.grid3 {
  width: 700px;
  height: 430px;
}
.red { color: red;  background-color: yellow !important; }
.blue { color: blue;  }
  • app.js
var app = angular.module('app', ['ngTouch', 'ngAria', 'ui.grid', 'ui.grid.pagination', 'ui.grid.cellNav']);

app.controller('MainCtrl', ['$scope', '$http', 'uiGridConstants', function ($scope, $http, uiGridConstants) {
  var setGender = function ( row, index ){
    row.gender = row.gender==='male' ? '1' : '2';
  };
  $scope.smallGrid = {
    enableSorting: true,
    showGridFooter: true,
    enableGridMenu: true,
    enableFiltering: true,
    columnDefs: [
      { field: 'firstName'},
      {
        field: 'lastName',
        filter: {
          placeholder: 'set sr focus here',
          ariaLabel: 'I have a custom aria label for this field.'
        }
      },
      {
        field: 'gender',
        filter: {
          type: uiGridConstants.filter.SELECT,
          selectOptions: [
            {value: '1', label: 'male'},
            {value: '2', label: 'female'},
          ],
        },
        cellFilter: 'mapGender'
      },
      { field: 'company' },
      { field: 'employed'},
    ],
    data: [
      {
          "firstName": "Cox",
          "lastName": "Carney",
          "gender": 1,
          "company": "Enormo",
          "employed": true
      },
      {
          "firstName": "Lorraine",
          "lastName": "Wise",
          "gender": 2,
          "company": "Comveyer",
          "employed": false
      },
      {
          "firstName": "Nancy",
          "lastName": "Waters",
          "gender": 2,
          "company": "Fuelton",
          "employed": false
      }
    ],
  };


  $scope.virtualGridOptions = {
    enableSorting: true,
    showGridFooter: true,
    enableFiltering: true,
    modifierKeysToMultiSelectCells: true,
    columnDefs: [
      { field: 'name'},
      { field: 'company'},
      { field: 'gender', cellTooltip: true, headerTooltip: true, cellFilter: 'mapGender' },
    ],
    onRegisterApi: function( gridApi ) {
      $scope.gridApi = gridApi;
      $scope.gridApi.core.on.sortChanged( $scope, function( grid, sort ) {
        $scope.gridApi.core.notifyDataChange( uiGridConstants.dataChange.COLUMN );
      })
    }
  };
  $scope.paginationGridOptions = {
    paginationPageSizes: [10, 25, 50, 75],
    paginationPageSize: 10,
  };
  angular.extend($scope.paginationGridOptions, $scope.virtualGridOptions);

  $http.get('http://ui-grid.info/data/100.json')
    .success(function(data) {
      data.forEach(setGender);
      $scope.virtualGridOptions.data = data;
      $scope.paginationGridOptions.data = data;
    });
}])
.filter('mapGender', function() {
  var genderHash = {
    1: 'male',
    2: 'female'
  };

  return function(input) {
    if (!input){
      return '';
    } else {
      return genderHash[input];
    }
  };
});

关注微信公众号,与我交流吧~

分享