From 81db93796d70b087c2283435d3eb3d90814f1a8a Mon Sep 17 00:00:00 2001 From: Marcy Sutton Date: Thu, 12 Feb 2015 16:58:51 -0800 Subject: [PATCH] fix(autocomplete): announce changes with ARIA WIP: needs to announce match count change when user re-filters list by deleting a character. Closes #1473 --- .../autocomplete/js/autocompleteController.js | 33 +++++++++++++++++++ .../autocomplete/js/autocompleteDirective.js | 5 ++- 2 files changed, 35 insertions(+), 3 deletions(-) diff --git a/src/components/autocomplete/js/autocompleteController.js b/src/components/autocomplete/js/autocompleteController.js index 0c4dcfa33e1..176414b5f52 100644 --- a/src/components/autocomplete/js/autocompleteController.js +++ b/src/components/autocomplete/js/autocompleteController.js @@ -66,6 +66,21 @@ self.fetch(searchText); } }); + + $scope.$watch('matchCount', function(matchCount) { + if (matchCount > 0) { + var matchWords = { + verb: 'are', + noun: 'matches' + }; + if (matchCount === 1) { + matchWords.verb = 'is'; + matchWords.noun = 'match'; + } + var string = 'There '+matchWords.verb+ ' '+matchCount +' '+matchWords.noun+ ' available.'; + setAriaStatus(string); + } + }); } function fetchResults (searchText) { @@ -73,6 +88,11 @@ term = searchText.toLowerCase(); promise = $q.when(items).then(function (matches) { cache[term] = matches; + + // how can we announce a change in matches + // even with the cache? + $scope.matchCount = matches.length; + if (searchText !== $scope.searchText) return; //-- just cache the results if old request promise = null; self.loading = false; @@ -86,12 +106,14 @@ if (self.loading) return; event.preventDefault(); self.index = Math.min(self.index + 1, self.matches.length - 1); + setAriaStatus(getSelectedItemText()); updateScroll(); break; case $mdConstant.KEY_CODE.UP_ARROW: if (self.loading) return; event.preventDefault(); self.index = Math.max(0, self.index - 1); + setAriaStatus(getSelectedItemText()); updateScroll(); break; case $mdConstant.KEY_CODE.ENTER: @@ -129,11 +151,22 @@ function select (index) { $scope.selectedItem = self.matches[index]; $scope.searchText = getDisplayValue($scope.selectedItem) || $scope.searchText; + if ($scope.searchText) { + setAriaStatus($scope.searchText); + } self.hidden = true; self.index = -1; self.matches = []; } + function getSelectedItemText () { + return self.matches[self.index].display; + } + + function setAriaStatus (text) { + $scope.hintText = text; + } + function updateScroll () { var top = 41 * self.index, bot = top + 41, diff --git a/src/components/autocomplete/js/autocompleteDirective.js b/src/components/autocomplete/js/autocompleteDirective.js index 5dbdf60f4b1..c3f061c8765 100644 --- a/src/components/autocomplete/js/autocompleteDirective.js +++ b/src/components/autocomplete/js/autocompleteDirective.js @@ -64,10 +64,9 @@ \ \ -

{{item.display}}

\ + aria-live="assertive">\ +

{{hintText}}

\ ', transclude: true, controller: 'MdAutocompleteCtrl',