1010var _ = function ( input , o ) {
1111 var me = this ;
1212
13- // Keep track of number of instances for unique IDs
14- _ . count = ( _ . count || 0 ) + 1 ;
15- this . count = _ . count ;
13+ // Keep track of number of instances for unique IDs
14+ _ . count = ( _ . count || 0 ) + 1 ;
15+ this . count = _ . count ;
1616
1717 // Setup
1818
1919 this . isOpened = false ;
2020
2121 this . input = $ ( input ) ;
2222 this . input . setAttribute ( "autocomplete" , "off" ) ;
23+ this . input . setAttribute ( "aria-autocomplete" , "list" ) ;
2324 this . input . setAttribute ( "aria-expanded" , "false" ) ;
2425 this . input . setAttribute ( "aria-owns" , "awesomplete_list_" + this . count ) ;
2526 this . input . setAttribute ( "role" , "combobox" ) ;
@@ -39,7 +40,10 @@ var _ = function (input, o) {
3940 item : _ . ITEM ,
4041 replace : _ . REPLACE ,
4142 tabSelect : false ,
42- listLabel : "Results List"
43+ listLabel : "Results List" ,
44+ statusNoResults : "No results found" ,
45+ statusXResults : "{0} results found" , // uses index placeholder {0}
46+ statusTypeXChar : "Type {0} or more characters for results"
4347 } , o ) ;
4448
4549 this . index = - 1 ;
@@ -50,8 +54,8 @@ var _ = function (input, o) {
5054
5155 this . ul = $ . create ( "ul" , {
5256 hidden : "hidden" ,
53- role : "listbox" ,
54- id : "awesomplete_list_" + this . count ,
57+ role : "listbox" ,
58+ id : "awesomplete_list_" + this . count ,
5559 inside : this . container ,
5660 "aria-label" : this . listLabel
5761 } ) ;
@@ -60,9 +64,9 @@ var _ = function (input, o) {
6064 className : "visually-hidden" ,
6165 role : "status" ,
6266 "aria-live" : "assertive" ,
63- "aria-atomic" : true ,
64- inside : this . container ,
65- textContent : this . minChars != 0 ? ( "Type " + this . minChars + " or more characters for results." ) : "Begin typing for results."
67+ "aria-atomic" : true ,
68+ inside : this . container ,
69+ textContent : "" // live region should start empty. Only when the text is changed it will be read by the screen reader.
6670 } ) ;
6771
6872 // Bind events
@@ -222,9 +226,12 @@ _.prototype = {
222226 parentNode . removeChild ( this . container ) ;
223227 }
224228
225- //remove autocomplete and aria-autocomplete attributes
229+ // remove autocomplete and aria attributes
226230 this . input . removeAttribute ( "autocomplete" ) ;
227231 this . input . removeAttribute ( "aria-autocomplete" ) ;
232+ this . input . removeAttribute ( "aria-expanded" ) ;
233+ this . input . removeAttribute ( "aria-owns" ) ;
234+ this . input . removeAttribute ( "role" ) ;
228235
229236 //remove this awesomeplete instance from the global array of instances
230237 var indexOfAwesomplete = _ . all . indexOf ( this ) ;
@@ -259,9 +266,12 @@ _.prototype = {
259266 if ( i > - 1 && lis . length > 0 ) {
260267 lis [ i ] . setAttribute ( "aria-selected" , "true" ) ;
261268
262- this . status . textContent = lis [ i ] . textContent + ", list item " + ( i + 1 ) + " of " + lis . length ;
269+ // fix: Turned off this status update.
270+ // Screen readers Voiceover and Talkback won't read this status change.
271+ // Narrator and NVDA do, but they already tell: 'X of Y (selected)'
272+ // this.status.textContent = lis[i].textContent + ", list item " + (i + 1) + " of " + lis.length;
263273
264- this . input . setAttribute ( "aria-activedescendant" , this . ul . id + "_item_" + this . index ) ;
274+ this . input . setAttribute ( "aria-activedescendant" , this . ul . id + "_item_" + this . index ) ;
265275
266276 // scroll to highlighted element in case parent's height is fixed
267277 this . ul . scrollTop = lis [ i ] . offsetTop - this . ul . clientHeight + lis [ i ] . clientHeight ;
@@ -328,20 +338,26 @@ _.prototype = {
328338
329339 if ( this . ul . children . length === 0 ) {
330340
331- this . status . textContent = "No results found" ;
341+ this . status . textContent = this . statusNoResults ;
332342
333343 this . close ( { reason : "nomatches" } ) ;
334344
335345 } else {
336346 this . open ( ) ;
337347
338- this . status . textContent = this . ul . children . length + " results found" ;
348+ this . status . textContent = this . statusXResults . replaceAll ( '{0}' , this . ul . children . length ) ; // N results found;
339349 }
340350 }
341351 else {
352+
342353 this . close ( { reason : "nomatches" } ) ;
343354
344- this . status . textContent = "No results found" ;
355+ if ( this . minChar <= 1 || value . length >= this . minChars ) {
356+ this . status . textContent = this . statusNoResults ;
357+ } else {
358+ this . status . textContent = this . statusTypeXChar . replaceAll ( '{0}' , this . minChars ) ; // Type N or more characters for results
359+ }
360+
345361 }
346362 }
347363} ;
@@ -379,6 +395,7 @@ _.ITEM = function (text, input, item_id) {
379395 innerHTML : html ,
380396 "role" : "option" ,
381397 "aria-selected" : "false" ,
398+ "tabindex" : '0' , // for the Talkback screen reader
382399 "id" : "awesomplete_list_" + this . count + "_item_" + item_id
383400 } ) ;
384401} ;
@@ -409,7 +426,7 @@ Suggestion.prototype.toString = Suggestion.prototype.valueOf = function () {
409426function configure ( instance , properties , o ) {
410427 for ( var i in properties ) {
411428 var initial = properties [ i ] ,
412- attrValue = instance . input . getAttribute ( "data-" + i . toLowerCase ( ) ) ;
429+ attrValue = instance . input . getAttribute ( "data-" + i . toLowerCase ( ) ) ;
413430
414431 if ( typeof initial === "number" ) {
415432 instance [ i ] = parseInt ( attrValue ) ;
0 commit comments