@@ -843,7 +843,7 @@ export class MultipleSelectInstance {
843
843
}
844
844
// move highlight back to top of the list
845
845
this . _currentHighlightIndex = - 1 ;
846
- this . moveFocusDown ( ) ;
846
+ this . moveHighlightDown ( ) ;
847
847
this . filter ( ) ;
848
848
} ) as EventListener ) ;
849
849
}
@@ -993,7 +993,7 @@ export class MultipleSelectInstance {
993
993
this . _bindEventService . bind (
994
994
this . dropElm ,
995
995
'mouseover' ,
996
- ( ( e : KeyboardEvent & { target : HTMLDivElement | HTMLLIElement } ) => {
996
+ ( ( e : MouseEvent & { target : HTMLDivElement | HTMLLIElement } ) => {
997
997
const liElm = ( e . target . closest ( '.ms-select-all' ) || e . target . closest ( 'li' ) ) as HTMLLIElement ;
998
998
if ( this . dropElm . contains ( liElm ) ) {
999
999
const optionElms = this . dropElm ?. querySelectorAll < HTMLLIElement > ( OPTIONS_LIST_SELECTOR ) || [ ] ;
@@ -1019,28 +1019,49 @@ export class MultipleSelectInstance {
1019
1019
switch ( e . key ) {
1020
1020
case 'ArrowUp' :
1021
1021
e . preventDefault ( ) ;
1022
- this . moveFocusUp ( ) ;
1022
+ this . moveHighlightUp ( ) ;
1023
1023
break ;
1024
1024
case 'ArrowDown' :
1025
1025
e . preventDefault ( ) ;
1026
- this . moveFocusDown ( ) ;
1026
+ this . moveHighlightDown ( ) ;
1027
1027
break ;
1028
1028
case 'Enter' :
1029
1029
case ' ' : {
1030
- const liElm = e . target . closest ( '.ms-select-all' ) || e . target . closest ( 'li' ) ;
1031
- if ( ( e . key === ' ' && this . options . filter ) || ( this . options . filterAcceptOnEnter && ! liElm ) ) {
1032
- return ;
1033
- }
1034
- e . preventDefault ( ) ;
1035
- this . _currentSelectedElm ?. querySelector ( 'input' ) ?. click ( ) ;
1030
+ // if we're focused on the OK button then don't execute following block
1031
+ if ( document . activeElement !== this . okButtonElm ) {
1032
+ const liElm = e . target . closest ( '.ms-select-all' ) || e . target . closest ( 'li' ) ;
1033
+ if ( ( e . key === ' ' && this . options . filter ) || ( this . options . filterAcceptOnEnter && ! liElm ) ) {
1034
+ return ;
1035
+ }
1036
+ e . preventDefault ( ) ;
1037
+ this . _currentSelectedElm ?. querySelector ( 'input' ) ?. click ( ) ;
1036
1038
1037
- // on single select, we should focus directly
1038
- if ( this . options . single ) {
1039
- this . choiceElm . focus ( ) ;
1040
- this . lastFocusedItemKey = this . choiceElm ?. dataset . key || '' ;
1039
+ // on single select, we should focus directly
1040
+ if ( this . options . single ) {
1041
+ this . choiceElm . focus ( ) ;
1042
+ this . lastFocusedItemKey = this . choiceElm ?. dataset . key || '' ;
1043
+ }
1041
1044
}
1042
1045
break ;
1043
1046
}
1047
+ case 'Tab' : {
1048
+ // when clicking Tab, we'll focus on OK button when available
1049
+ // or with Shift+Tab we'll either focus first option when coming
1050
+ // from OK button or close drop if we're already in the lsit
1051
+ e . preventDefault ( ) ;
1052
+ if ( e . shiftKey ) {
1053
+ if ( document . activeElement === this . okButtonElm ) {
1054
+ this . focusSelectAllOrList ( ) ;
1055
+ this . highlightCurrentOption ( ) ;
1056
+ } else {
1057
+ this . close ( ) ;
1058
+ this . choiceElm . focus ( ) ;
1059
+ }
1060
+ } else {
1061
+ this . changeCurrentOptionHighlight ( ) ;
1062
+ this . okButtonElm ?. focus ( ) ;
1063
+ }
1064
+ }
1044
1065
}
1045
1066
} ) as EventListener ,
1046
1067
undefined ,
@@ -1135,12 +1156,12 @@ export class MultipleSelectInstance {
1135
1156
if ( this . options . maxHeightUnit === 'row' ) {
1136
1157
maxHeight = getElementSize ( this . dropElm . querySelector ( 'ul>li' ) as HTMLLIElement , 'outer' , 'height' ) * this . options . maxHeight ;
1137
1158
}
1138
- const ulElm = this . dropElm . querySelector ( 'ul' ) ;
1139
- if ( ulElm ) {
1159
+ this . ulElm ?? = this . dropElm . querySelector ( 'ul' ) ;
1160
+ if ( this . ulElm ) {
1140
1161
if ( minHeight ) {
1141
- ulElm . style . minHeight = `${ minHeight } px` ;
1162
+ this . ulElm . style . minHeight = `${ minHeight } px` ;
1142
1163
}
1143
- ulElm . style . maxHeight = `${ maxHeight } px` ;
1164
+ this . ulElm . style . maxHeight = `${ maxHeight } px` ;
1144
1165
}
1145
1166
this . dropElm . querySelectorAll < HTMLDivElement > ( '.multiple' ) . forEach ( multElm => {
1146
1167
multElm . style . width = `${ this . options . multipleWidth } px` ;
@@ -1154,17 +1175,12 @@ export class MultipleSelectInstance {
1154
1175
this . filter ( true ) ;
1155
1176
} else {
1156
1177
// highlight SelectAll or 1st select option when opening dropdown
1157
- if ( this . selectAllElm ) {
1158
- this . selectAllElm . focus ( ) ;
1159
- } else if ( ulElm ) {
1160
- ulElm . tabIndex = 0 ;
1161
- ulElm . focus ( ) ;
1162
- }
1178
+ this . focusSelectAllOrList ( ) ;
1163
1179
}
1164
1180
1165
1181
if ( this . _currentHighlightIndex < 0 ) {
1166
1182
// on open drop initial, we'll focus on next available option
1167
- this . moveFocusDown ( ) ;
1183
+ this . moveHighlightDown ( ) ;
1168
1184
} else {
1169
1185
// if it was already opened earlier, we'll keep same option index focused
1170
1186
this . highlightCurrentOption ( ) ;
@@ -1195,6 +1211,15 @@ export class MultipleSelectInstance {
1195
1211
this . options . onOpen ( ) ;
1196
1212
}
1197
1213
1214
+ protected focusSelectAllOrList ( ) {
1215
+ if ( this . selectAllElm ) {
1216
+ this . selectAllElm . focus ( ) ;
1217
+ } else if ( this . ulElm ) {
1218
+ this . ulElm . tabIndex = 0 ;
1219
+ this . ulElm . focus ( ) ;
1220
+ }
1221
+ }
1222
+
1198
1223
protected highlightCurrentOption ( ) {
1199
1224
const optionElms = this . dropElm ?. querySelectorAll < HTMLLIElement > ( OPTIONS_LIST_SELECTOR ) || [ ] ;
1200
1225
@@ -1212,8 +1237,9 @@ export class MultipleSelectInstance {
1212
1237
}
1213
1238
}
1214
1239
1215
- protected changeCurrentOptionHighlight ( optionElm : HTMLLIElement | HTMLDivElement ) {
1216
- optionElm . classList . add ( 'highlighted' ) ;
1240
+ /** Change highlighted option, or remove highlight when nothing is provided */
1241
+ protected changeCurrentOptionHighlight ( optionElm ?: HTMLLIElement | HTMLDivElement ) {
1242
+ optionElm ?. classList . add ( 'highlighted' ) ;
1217
1243
const currentElms = this . dropElm ?. querySelectorAll < HTMLLIElement > ( OPTIONS_HIGHLIGHT_LIST_SELECTOR ) || [ ] ;
1218
1244
currentElms . forEach ( option => {
1219
1245
if ( option !== optionElm ) {
@@ -1222,18 +1248,18 @@ export class MultipleSelectInstance {
1222
1248
} ) ;
1223
1249
}
1224
1250
1225
- protected moveFocusDown ( ) {
1251
+ protected moveHighlightDown ( ) {
1226
1252
const optionElms = this . dropElm ?. querySelectorAll < HTMLLIElement > ( OPTIONS_LIST_SELECTOR ) || [ ] ;
1227
1253
if ( this . _currentHighlightIndex < optionElms . length - 1 ) {
1228
1254
this . _currentHighlightIndex ++ ;
1229
1255
if ( optionElms [ this . _currentHighlightIndex ] ?. classList . contains ( 'disabled' ) ) {
1230
- this . moveFocusDown ( ) ;
1256
+ this . moveHighlightDown ( ) ;
1231
1257
}
1232
1258
}
1233
1259
this . highlightCurrentOption ( ) ;
1234
1260
}
1235
1261
1236
- protected moveFocusUp ( ) {
1262
+ protected moveHighlightUp ( ) {
1237
1263
const optionElms = this . dropElm ?. querySelectorAll < HTMLLIElement > ( OPTIONS_LIST_SELECTOR ) || [ ] ;
1238
1264
const idxToCompare = this . options . single ? 0 : 1 ;
1239
1265
if ( this . virtualScroll && this . _currentHighlightIndex <= idxToCompare && this . updateDataStart ! > 0 && this . ulElm ) {
@@ -1252,7 +1278,7 @@ export class MultipleSelectInstance {
1252
1278
if ( this . _currentHighlightIndex > 0 ) {
1253
1279
this . _currentHighlightIndex -- ;
1254
1280
if ( optionElms [ this . _currentHighlightIndex ] ?. classList . contains ( 'disabled' ) ) {
1255
- this . moveFocusUp ( ) ;
1281
+ this . moveHighlightUp ( ) ;
1256
1282
}
1257
1283
}
1258
1284
@@ -1264,9 +1290,9 @@ export class MultipleSelectInstance {
1264
1290
const newIdx = Array . from ( optionElms ) . findIndex ( el => el . dataset . key === this . lastFocusedItemKey ) ;
1265
1291
this . _currentHighlightIndex = newIdx - 1 ;
1266
1292
if ( direction === 'down' ) {
1267
- this . moveFocusDown ( ) ;
1293
+ this . moveHighlightDown ( ) ;
1268
1294
} else if ( direction === 'up' ) {
1269
- this . moveFocusUp ( ) ;
1295
+ this . moveHighlightUp ( ) ;
1270
1296
this . isMoveUpRecalcRequired = false ;
1271
1297
}
1272
1298
}
0 commit comments