@@ -17,6 +17,7 @@ $.widget("ui.selectmenu", {
17
17
eventPrefix : "selectmenu" ,
18
18
options : {
19
19
transferClasses : true ,
20
+ typeAhead : "sequential" ,
20
21
style : 'dropdown' ,
21
22
positionOptions : {
22
23
my : "left top" ,
@@ -37,10 +38,10 @@ $.widget("ui.selectmenu", {
37
38
var self = this , o = this . options ;
38
39
39
40
// set a default id value
40
- var selectmenuId = this . element . attr ( 'id' ) || 'ui-selectmenu-' + Math . random ( ) . toString ( 16 ) . slice ( 2 , 10 ) ;
41
+ this . selectmenuId = this . element . attr ( 'id' ) || 'ui-selectmenu-' + Math . random ( ) . toString ( 16 ) . slice ( 2 , 10 ) ;
41
42
42
43
//quick array of button and menu id's
43
- this . ids = [ selectmenuId + '-' + 'button' , selectmenuId + '-' + 'menu' ] ;
44
+ this . ids = [ this . selectmenuId + '-' + 'button' , this . selectmenuId + '-' + 'menu' ] ;
44
45
45
46
//define safe mouseup for future toggling
46
47
this . _safemouseup = true ;
@@ -206,6 +207,7 @@ $.widget("ui.selectmenu", {
206
207
break ;
207
208
default :
208
209
ret = true ;
210
+ self . _typeAhead ( event . keyCode , 'focus' ) ;
209
211
break ;
210
212
}
211
213
return ret ;
@@ -229,6 +231,7 @@ $.widget("ui.selectmenu", {
229
231
text : self . _formatText ( $ ( this ) . text ( ) ) ,
230
232
selected : $ ( this ) . attr ( 'selected' ) ,
231
233
classes : $ ( this ) . attr ( 'class' ) ,
234
+ typeahead : $ ( this ) . attr ( 'typeahead' ) ,
232
235
parentOptGroup : $ ( this ) . parent ( 'optgroup' ) . attr ( 'label' ) ,
233
236
bgImage : o . bgImage . call ( $ ( this ) )
234
237
} ) ;
@@ -242,7 +245,8 @@ $.widget("ui.selectmenu", {
242
245
243
246
//write li's
244
247
for ( var i = 0 ; i < selectOptionData . length ; i ++ ) {
245
- var thisLi = $ ( '<li role="presentation"><a href="#" tabindex="-1" role="option" aria-selected="false">' + selectOptionData [ i ] . text + '</a></li>' )
248
+
249
+ var thisLi = $ ( '<li role="presentation"><a href="#" tabindex="-1" role="option" aria-selected="false"' + ( selectOptionData [ i ] . typeahead ? ' typeahead="' + selectOptionData [ i ] . typeahead + '"' : '' ) + '>' + selectOptionData [ i ] . text + '</a></li>' )
246
250
. data ( 'index' , i )
247
251
. addClass ( selectOptionData [ i ] . classes )
248
252
. data ( 'optionClasses' , selectOptionData [ i ] . classes || '' )
@@ -391,29 +395,67 @@ $.widget("ui.selectmenu", {
391
395
$ . Widget . prototype . destroy . apply ( this , arguments ) ;
392
396
} ,
393
397
_typeAhead : function ( code , eventType ) {
394
- var self = this ;
395
- //define self._prevChar if needed
396
- if ( ! self . _prevChar ) { self . _prevChar = [ '' , 0 ] ; }
397
- var C = String . fromCharCode ( code ) ;
398
+ var self = this , focusFound = false , C = String . fromCharCode ( code ) ;
398
399
c = C . toLowerCase ( ) ;
399
- var focusFound = false ;
400
- function focusOpt ( elem , ind ) {
401
- focusFound = true ;
402
- $ ( elem ) . trigger ( eventType ) ;
403
- self . _prevChar [ 1 ] = ind ;
404
- }
405
- this . list . find ( 'li a' ) . each ( function ( i ) {
406
- if ( ! focusFound ) {
407
- var thisText = $ ( this ) . text ( ) ;
408
- if ( thisText . indexOf ( C ) == 0 || thisText . indexOf ( c ) == 0 ) {
409
- if ( self . _prevChar [ 0 ] == C ) {
410
- if ( self . _prevChar [ 1 ] < i ) { focusOpt ( this , i ) ; }
411
- }
412
- else { focusOpt ( this , i ) ; }
400
+
401
+ if ( self . options . typeAhead == 'sequential' ) {
402
+ // clear the timeout so we can use _prevChar
403
+ window . clearTimeout ( 'ui.selectmenu-' + self . selectmenuId ) ;
404
+
405
+ // define our find var
406
+ var find = typeof ( self . _prevChar ) == 'undefined' ? '' : self . _prevChar . join ( '' ) ;
407
+
408
+ function focusOptSeq ( elem , ind , char ) {
409
+ focusFound = true ;
410
+ $ ( elem ) . trigger ( eventType ) ;
411
+ typeof ( self . _prevChar ) == 'undefined' ? self . _prevChar = [ char ] : self . _prevChar [ self . _prevChar . length ] = char ;
412
+ }
413
+ this . list . find ( 'li a' ) . each ( function ( i ) {
414
+ if ( ! focusFound ) {
415
+ // allow the typeahead attribute on the option tag for a more specific lookup
416
+ var thisText = $ ( this ) . attr ( 'typeahead' ) || $ ( this ) . text ( ) ;
417
+ if ( thisText . indexOf ( find + C ) == 0 ) {
418
+ focusOptSeq ( this , i , C )
419
+ } else if ( thisText . indexOf ( find + c ) == 0 ) {
420
+ focusOptSeq ( this , i , c )
421
+ }
413
422
}
423
+ } ) ;
424
+
425
+ // if we didnt find it clear the prevChar
426
+ if ( ! focusFound ) {
427
+ //self._prevChar = undefined
414
428
}
415
- } ) ;
416
- this . _prevChar [ 0 ] = C ;
429
+
430
+ // set a 1 second timeout for sequenctial typeahead
431
+ // keep this set even if we have no matches so it doesnt typeahead somewhere else
432
+ window . setTimeout ( function ( el ) {
433
+ el . _prevChar = undefined ;
434
+ } , 1000 , self ) ;
435
+
436
+ } else {
437
+ //define self._prevChar if needed
438
+ if ( ! self . _prevChar ) { self . _prevChar = [ '' , 0 ] ; }
439
+
440
+ var focusFound = false ;
441
+ function focusOpt ( elem , ind ) {
442
+ focusFound = true ;
443
+ $ ( elem ) . trigger ( eventType ) ;
444
+ self . _prevChar [ 1 ] = ind ;
445
+ }
446
+ this . list . find ( 'li a' ) . each ( function ( i ) {
447
+ if ( ! focusFound ) {
448
+ var thisText = $ ( this ) . text ( ) ;
449
+ if ( thisText . indexOf ( C ) == 0 || thisText . indexOf ( c ) == 0 ) {
450
+ if ( self . _prevChar [ 0 ] == C ) {
451
+ if ( self . _prevChar [ 1 ] < i ) { focusOpt ( this , i ) ; }
452
+ }
453
+ else { focusOpt ( this , i ) ; }
454
+ }
455
+ }
456
+ } ) ;
457
+ this . _prevChar [ 0 ] = C ;
458
+ }
417
459
} ,
418
460
// returns some usefull information, called by callbacks only
419
461
_uiHash : function ( ) {
0 commit comments