@@ -9,6 +9,11 @@ angular.module('material.components.radioButton', [
9
9
. directive ( 'mdRadioGroup' , mdRadioGroupDirective )
10
10
. directive ( 'mdRadioButton' , mdRadioButtonDirective ) ;
11
11
12
+ /**
13
+ * @type {Readonly<{NEXT: number, CURRENT: number, PREVIOUS: number}> }
14
+ */
15
+ var incrementSelection = Object . freeze ( { PREVIOUS : - 1 , CURRENT : 0 , NEXT : 1 } ) ;
16
+
12
17
/**
13
18
* @ngdoc directive
14
19
* @module material.components.radioButton
@@ -106,33 +111,38 @@ function mdRadioGroupDirective($mdUtil, $mdConstant, $mdTheming, $timeout) {
106
111
}
107
112
108
113
/**
109
- * @param {KeyboardEvent } ev
114
+ * @param {KeyboardEvent } keyboardEvent
110
115
*/
111
- function keydownListener ( ev ) {
112
- var keyCode = ev . which || ev . keyCode ;
116
+ function keydownListener ( keyboardEvent ) {
117
+ var keyCode = keyboardEvent . which || keyboardEvent . keyCode ;
113
118
114
119
// Only listen to events that we originated ourselves
115
120
// so that we don't trigger on things like arrow keys in inputs.
116
121
if ( keyCode !== $mdConstant . KEY_CODE . ENTER &&
117
- ev . currentTarget !== ev . target ) {
122
+ keyboardEvent . currentTarget !== keyboardEvent . target ) {
118
123
return ;
119
124
}
120
125
121
126
switch ( keyCode ) {
122
127
case $mdConstant . KEY_CODE . LEFT_ARROW :
123
128
case $mdConstant . KEY_CODE . UP_ARROW :
124
- ev . preventDefault ( ) ;
129
+ keyboardEvent . preventDefault ( ) ;
125
130
radioGroupController . selectPrevious ( ) ;
126
131
setFocus ( ) ;
127
132
break ;
128
133
129
134
case $mdConstant . KEY_CODE . RIGHT_ARROW :
130
135
case $mdConstant . KEY_CODE . DOWN_ARROW :
131
- ev . preventDefault ( ) ;
136
+ keyboardEvent . preventDefault ( ) ;
132
137
radioGroupController . selectNext ( ) ;
133
138
setFocus ( ) ;
134
139
break ;
135
140
141
+ case $mdConstant . KEY_CODE . SPACE :
142
+ keyboardEvent . preventDefault ( ) ;
143
+ radioGroupController . selectCurrent ( ) ;
144
+ break ;
145
+
136
146
case $mdConstant . KEY_CODE . ENTER :
137
147
var form = angular . element ( $mdUtil . getClosest ( element [ 0 ] , 'form' ) ) ;
138
148
if ( form . length > 0 ) {
@@ -180,11 +190,14 @@ function mdRadioGroupDirective($mdUtil, $mdConstant, $mdTheming, $timeout) {
180
190
getViewValue : function ( ) {
181
191
return this . _ngModelCtrl . $viewValue ;
182
192
} ,
193
+ selectCurrent : function ( ) {
194
+ return changeSelectedButton ( this . $element , incrementSelection . CURRENT ) ;
195
+ } ,
183
196
selectNext : function ( ) {
184
- return changeSelectedButton ( this . $element , 1 ) ;
197
+ return changeSelectedButton ( this . $element , incrementSelection . NEXT ) ;
185
198
} ,
186
199
selectPrevious : function ( ) {
187
- return changeSelectedButton ( this . $element , - 1 ) ;
200
+ return changeSelectedButton ( this . $element , incrementSelection . PREVIOUS ) ;
188
201
} ,
189
202
setActiveDescendant : function ( radioId ) {
190
203
this . $element . attr ( 'aria-activedescendant' , radioId ) ;
@@ -196,9 +209,9 @@ function mdRadioGroupDirective($mdUtil, $mdConstant, $mdTheming, $timeout) {
196
209
}
197
210
198
211
/**
199
- * Coerce all child radio buttons into an array, then wrap then in an iterator
212
+ * Coerce all child radio buttons into an array, then wrap them in an iterator.
200
213
* @param parent {!JQLite}
201
- * @return {{add: function(*=, *=): *, next: Function , last: function(): * , previous: Function , count: function(): (Array.length|*| number), hasNext: function(*=): ( Array.length|*|number|boolean), inRange: function(*): (Array.length|*|number| boolean), remove: function(*=): void , contains: function(*=): boolean, itemAt: function(*=): * , findBy: function(*, *): Array , hasPrevious: function(*=): ( Array.length|*|number|boolean), items: function(): (Array|* ), indexOf: function(*=): * , first: function(): *}|Object|*|AsyncIterableIterator<OctokitTypes.OctokitResponse<PaginationResults< any>>> }
214
+ * @return {{add: add, next: (function()) , last: ( function(): any|null) , previous: (function()) , count: ( function(): number), hasNext: ( function(*=): Array.length|*|number|boolean), inRange: ( function(*): boolean), remove: remove , contains: ( function(*=): *| boolean) , itemAt: ( function(*=): any|null) , findBy: ( function(*, *): *[]) , hasPrevious: ( function(*=): Array.length|*|number|boolean), items: ( function(): *[] ), indexOf: ( function(*=): number) , first: ( function(): any|null)} }
202
215
*/
203
216
function getRadioButtons ( parent ) {
204
217
return $mdUtil . iterator ( parent [ 0 ] . querySelectorAll ( 'md-radio-button' ) , true ) ;
@@ -207,12 +220,14 @@ function mdRadioGroupDirective($mdUtil, $mdConstant, $mdTheming, $timeout) {
207
220
/**
208
221
* Change the radio group's selected button by a given increment.
209
222
* If no button is selected, select the first button.
210
- * @param {JQLite } parent
211
- * @param {-1|1 } increment select previous button if the value is negative; the next button
212
- * otherwise.
223
+ * @param {JQLite } parent the md-radio-group
224
+ * @param {incrementSelection } increment enum that determines whether the next or
225
+ * previous button is clicked. For current, only the first button is selected, otherwise the
226
+ * current selection is maintained (by doing nothing).
213
227
*/
214
228
function changeSelectedButton ( parent , increment ) {
215
229
var buttons = getRadioButtons ( parent ) ;
230
+ var target ;
216
231
217
232
if ( buttons . count ( ) ) {
218
233
var validate = function ( button ) {
@@ -221,11 +236,19 @@ function mdRadioGroupDirective($mdUtil, $mdConstant, $mdTheming, $timeout) {
221
236
} ;
222
237
223
238
var selected = parent [ 0 ] . querySelector ( 'md-radio-button.md-checked' ) ;
224
- var target = buttons [ increment < 0 ? 'previous' : 'next' ] ( selected , validate ) ||
225
- buttons . first ( ) ;
239
+ if ( ! selected ) {
240
+ target = buttons . first ( ) ;
241
+ } else if ( increment === incrementSelection . PREVIOUS ||
242
+ increment === incrementSelection . NEXT ) {
243
+ target = buttons [
244
+ increment === incrementSelection . PREVIOUS ? 'previous' : 'next'
245
+ ] ( selected , validate ) ;
246
+ }
226
247
227
- // Activate radioButton's click listener (triggerHandler won't create a real click event)
228
- angular . element ( target ) . triggerHandler ( 'click' ) ;
248
+ if ( target ) {
249
+ // Activate radioButton's click listener (triggerHandler won't create a real click event)
250
+ angular . element ( target ) . triggerHandler ( 'click' ) ;
251
+ }
229
252
}
230
253
}
231
254
}
0 commit comments