@@ -116,6 +116,8 @@ angular.module('ui.select', [])
116116 ctrl . items = [ ] ;
117117 ctrl . selected = undefined ;
118118 ctrl . open = false ;
119+ ctrl . focus = false ;
120+ ctrl . focusser = undefined ; //Reference to input element used to handle focus events
119121 ctrl . disabled = undefined ; // Initialized inside uiSelect directive link function
120122 ctrl . resetSearchInput = undefined ; // Initialized inside uiSelect directive link function
121123 ctrl . refreshDelay = undefined ; // Initialized inside uiSelectChoices directive link function
@@ -137,13 +139,14 @@ angular.module('ui.select', [])
137139 }
138140
139141 // When the user clicks on ui-select, displays the dropdown list
140- ctrl . activate = function ( ) {
142+ ctrl . activate = function ( initSearchValue ) {
141143 if ( ! ctrl . disabled ) {
142144 _resetSearchInput ( ) ;
143145 ctrl . open = true ;
144146
145147 // Give it time to appear before focus
146148 $timeout ( function ( ) {
149+ ctrl . search = initSearchValue || ctrl . search ;
147150 _searchInput [ 0 ] . focus ( ) ;
148151 } ) ;
149152 }
@@ -206,6 +209,7 @@ angular.module('ui.select', [])
206209 if ( ctrl . open ) {
207210 _resetSearchInput ( ) ;
208211 ctrl . open = false ;
212+ ctrl . focusser [ 0 ] . focus ( ) ;
209213 }
210214 } ;
211215
@@ -288,8 +292,8 @@ angular.module('ui.select', [])
288292} ] )
289293
290294. directive ( 'uiSelect' ,
291- [ '$document' , 'uiSelectConfig' , 'uiSelectMinErr' ,
292- function ( $document , uiSelectConfig , uiSelectMinErr ) {
295+ [ '$document' , 'uiSelectConfig' , 'uiSelectMinErr' , '$compile' ,
296+ function ( $document , uiSelectConfig , uiSelectMinErr , $compile ) {
293297
294298 return {
295299 restrict : 'EA' ,
@@ -309,6 +313,98 @@ angular.module('ui.select', [])
309313 var $select = ctrls [ 0 ] ;
310314 var ngModel = ctrls [ 1 ] ;
311315
316+ //Idea from: https://github.com/ivaynberg/select2/blob/79b5bf6db918d7560bdd959109b7bcfb47edaf43/select2.js#L1954
317+ var focusser = angular . element ( "<input ng-disabled='$select.disabled' class='ui-select-focusser ui-select-offscreen' type='text' aria-haspopup='true' role='button' />" ) ;
318+ $compile ( focusser ) ( scope ) ;
319+ $select . focusser = focusser ;
320+
321+ element . append ( focusser ) ;
322+ focusser . bind ( "focus" , function ( ) {
323+ scope . $evalAsync ( function ( ) {
324+ $select . focus = true ;
325+ } ) ;
326+ } ) ;
327+ focusser . bind ( "blur" , function ( ) {
328+ scope . $evalAsync ( function ( ) {
329+ $select . focus = false ;
330+ } ) ;
331+ } ) ;
332+ focusser . bind ( "keydown" , function ( e ) {
333+
334+ if ( e . which === KEY . TAB || KEY . isControl ( e ) || KEY . isFunctionKey ( e ) || e . which === KEY . ESC ) {
335+ return ;
336+ }
337+
338+ if ( e . which == KEY . DOWN || e . which == KEY . UP || e . which == KEY . ENTER || e . which == KEY . SPACE ) {
339+ e . preventDefault ( ) ;
340+ e . stopPropagation ( ) ;
341+ $select . activate ( ) ;
342+ }
343+
344+ scope . $digest ( ) ;
345+ } ) ;
346+
347+ focusser . bind ( "keyup input" , function ( e ) {
348+
349+ if ( e . which === KEY . TAB || KEY . isControl ( e ) || KEY . isFunctionKey ( e ) || e . which === KEY . ESC || e . which == KEY . ENTER ) {
350+ return ;
351+ }
352+
353+ $select . activate ( focusser . val ( ) ) ; //User pressed some regualar key, so we pass it to the search input
354+ focusser . val ( '' ) ;
355+ scope . $digest ( ) ;
356+
357+ } ) ;
358+
359+ //TODO Refactor to reuse the KEY object from uiSelectCtrl
360+ var KEY = {
361+ TAB : 9 ,
362+ ENTER : 13 ,
363+ ESC : 27 ,
364+ SPACE : 32 ,
365+ LEFT : 37 ,
366+ UP : 38 ,
367+ RIGHT : 39 ,
368+ DOWN : 40 ,
369+ SHIFT : 16 ,
370+ CTRL : 17 ,
371+ ALT : 18 ,
372+ PAGE_UP : 33 ,
373+ PAGE_DOWN : 34 ,
374+ HOME : 36 ,
375+ END : 35 ,
376+ BACKSPACE : 8 ,
377+ DELETE : 46 ,
378+ isArrow : function ( k ) {
379+ k = k . which ? k . which : k ;
380+ switch ( k ) {
381+ case KEY . LEFT :
382+ case KEY . RIGHT :
383+ case KEY . UP :
384+ case KEY . DOWN :
385+ return true ;
386+ }
387+ return false ;
388+ } ,
389+ isControl : function ( e ) {
390+ var k = e . which ;
391+ switch ( k ) {
392+ case KEY . SHIFT :
393+ case KEY . CTRL :
394+ case KEY . ALT :
395+ return true ;
396+ }
397+
398+ if ( e . metaKey ) return true ;
399+
400+ return false ;
401+ } ,
402+ isFunctionKey : function ( k ) {
403+ k = k . which ? k . which : k ;
404+ return k >= 112 && k <= 123 ;
405+ }
406+ } ;
407+
312408 attrs . $observe ( 'disabled' , function ( ) {
313409 // No need to use $eval() (thanks to ng-disabled) since we already get a boolean instead of a string
314410 $select . disabled = attrs . disabled !== undefined ? attrs . disabled : false ;
0 commit comments