@@ -17,7 +17,7 @@ $.widget("ui.selectmenu", {
17
17
eventPrefix : "selectmenu" ,
18
18
options : {
19
19
transferClasses : true ,
20
- typeAhead : "sequential" ,
20
+ typeAhead : 1000 ,
21
21
style : 'dropdown' ,
22
22
positionOptions : {
23
23
my : "left top" ,
@@ -131,13 +131,18 @@ $.widget("ui.selectmenu", {
131
131
case $ . ui . keyCode . TAB :
132
132
ret = true ;
133
133
break ;
134
+ case $ . ui . keyCode . HOME :
135
+ self . index ( 0 ) ;
136
+ break ;
134
137
default :
135
138
ret = true ;
136
139
}
137
140
return ret ;
138
141
} )
139
142
. bind ( 'keypress.selectmenu' , function ( event ) {
140
- self . _typeAhead ( event . which , 'mouseup' ) ;
143
+ if ( event . which > 0 ) {
144
+ self . _typeAhead ( event . which , 'mouseup' ) ;
145
+ }
141
146
return true ;
142
147
} )
143
148
. bind ( 'mouseover.selectmenu focus.selectmenu' , function ( ) {
@@ -250,7 +255,9 @@ $.widget("ui.selectmenu", {
250
255
return ret ;
251
256
} )
252
257
. bind ( 'keypress.selectmenu' , function ( event ) {
253
- self . _typeAhead ( event . which , 'focus' ) ;
258
+ if ( event . which > 0 ) {
259
+ self . _typeAhead ( event . which , 'focus' ) ;
260
+ }
254
261
return true ;
255
262
} )
256
263
// this allows for using the scrollbar in an overflowed list
@@ -460,63 +467,79 @@ $.widget("ui.selectmenu", {
460
467
$ . Widget . prototype . destroy . apply ( this , arguments ) ;
461
468
} ,
462
469
463
- _typeAhead : function ( code , eventType ) {
464
- var self = this , focusFound = false , C = String . fromCharCode ( code ) . toUpperCase ( ) ;
465
- c = C . toLowerCase ( ) ;
470
+ _typeAhead : function ( code , eventType ) {
471
+ var self = this ,
472
+ c = String . fromCharCode ( code ) . toLowerCase ( ) ,
473
+ items = this . list . find ( 'li a' ) ,
474
+ matchee = null ,
475
+ nextIndex = null ;
476
+
477
+ // Clear any previous timer if present
478
+ if ( self . _typeAhead_timer ) {
479
+ window . clearTimeout ( self . _typeAhead_timer ) ;
480
+ self . _typeAhead_timer = undefined ;
481
+ }
466
482
467
- if ( self . options . typeAhead == 'sequential' ) {
468
- // clear the timeout so we can use _prevChar
469
- window . clearTimeout ( 'ui.selectmenu-' + self . selectmenuId ) ;
483
+ // Store the character typed
484
+ self . _typeAhead_chars = ( self . _typeAhead_chars === undefined ? "" : self . _typeAhead_chars ) . concat ( c ) ;
470
485
471
- // define our find var
472
- var find = typeof ( self . _prevChar ) == 'undefined' ? '' : self . _prevChar . join ( '' ) ;
486
+ // Detect if we are in cyciling mode or direct selection mode
487
+ if ( self . _typeAhead_chars . length < 2 ||
488
+ ( self . _typeAhead_chars . substr ( - 2 , 1 ) === c && self . _typeAhead_cycling ) ) {
489
+ self . _typeAhead_cycling = true ;
473
490
474
- function focusOptSeq ( elem , ind , c ) {
475
- focusFound = true ;
476
- $ ( elem ) . trigger ( eventType ) ;
477
- typeof ( self . _prevChar ) == 'undefined' ? self . _prevChar = [ c ] : self . _prevChar [ self . _prevChar . length ] = c ;
478
- }
479
- this . list . find ( 'li a' ) . each ( function ( i ) {
480
- if ( ! focusFound ) {
481
- // allow the typeahead attribute on the option tag for a more specific lookup
482
- var thisText = $ ( this ) . attr ( 'typeahead' ) || $ ( this ) . text ( ) ;
483
- if ( thisText . indexOf ( find + C ) === 0 ) {
484
- focusOptSeq ( this , i , C ) ;
485
- } else if ( thisText . indexOf ( find + c ) === 0 ) {
486
- focusOptSeq ( this , i , c ) ;
487
- }
488
- }
489
- } ) ;
490
- // set a 1 second timeout for sequenctial typeahead
491
- // keep this set even if we have no matches so it doesnt typeahead somewhere else
492
- window . setTimeout ( function ( el ) {
493
- self . _prevChar = undefined ;
494
- } , 1000 , self ) ;
491
+ // Match only the first character and loop
492
+ matchee = c ;
493
+ }
494
+ else {
495
+ // We won't be cycling anymore until the timer expires
496
+ self . _typeAhead_cycling = false ;
495
497
496
- } else {
497
- // define self._prevChar if needed
498
- if ( ! self . _prevChar ) { self . _prevChar = [ '' , 0 ] ; }
499
-
500
- focusFound = false ;
501
- function focusOpt ( elem , ind ) {
502
- focusFound = true ;
503
- $ ( elem ) . trigger ( eventType ) ;
504
- self . _prevChar [ 1 ] = ind ;
505
- }
506
- this . list . find ( 'li a' ) . each ( function ( i ) {
507
- if ( ! focusFound ) {
508
- var thisText = $ ( this ) . text ( ) ;
509
- if ( thisText . indexOf ( C ) === 0 || thisText . indexOf ( c ) === 0 ) {
510
- if ( self . _prevChar [ 0 ] == C ) {
511
- if ( self . _prevChar [ 1 ] < i ) { focusOpt ( this , i ) ; }
512
- } else {
513
- focusOpt ( this , i ) ;
514
- }
498
+ // Match all the characters typed
499
+ matchee = self . _typeAhead_chars ;
500
+ }
501
+
502
+ // We need to determine the currently active index, but it depends on
503
+ // the used context: if it's in the element, we want the actual
504
+ // selected index, if it's in the menu, just the focused one
505
+ // I copied this code from _moveSelection() and _moveFocus()
506
+ // respectively --thg2k
507
+ var selectedIndex = ( eventType !== 'focus' ?
508
+ this . _selectedOptionLi ( ) . data ( 'index' ) :
509
+ this . _focusedOptionLi ( ) . data ( 'index' ) ) || 0 ;
510
+
511
+ for ( var i = 0 ; i < items . length ; i ++ ) {
512
+ var thisText = items . eq ( i ) . text ( ) . substr ( 0 , matchee . length ) . toLowerCase ( ) ;
513
+
514
+ if ( thisText === matchee ) {
515
+
516
+ if ( self . _typeAhead_cycling ) {
517
+ if ( nextIndex === null )
518
+ nextIndex = i ;
519
+
520
+ if ( i > selectedIndex ) {
521
+ nextIndex = i ;
522
+ break ;
515
523
}
524
+ } else {
525
+ nextIndex = i ;
516
526
}
517
- } ) ;
518
- this . _prevChar [ 0 ] = C ;
527
+ }
519
528
}
529
+
530
+ if ( nextIndex !== null ) {
531
+ // Why using trigger() instead of a direct method to select the
532
+ // index? Because we don't what is the exact action to do, it
533
+ // depends if the user is typing on the element or on the popped
534
+ // up menu
535
+ items . eq ( nextIndex ) . trigger ( eventType ) ;
536
+ }
537
+
538
+ self . _typeAhead_timer = window . setTimeout ( function ( ) {
539
+ self . _typeAhead_timer = undefined ;
540
+ self . _typeAhead_chars = undefined ;
541
+ self . _typeAhead_cycling = undefined ;
542
+ } , self . options . typeAhead ) ;
520
543
} ,
521
544
522
545
// returns some usefull information, called by callbacks only
0 commit comments