44
55var noopNgModelController = { $setViewValue : noop , $render : noop } ;
66
7+ function setOptionSelectedStatus ( optionEl , value ) {
8+ optionEl . prop ( 'selected' , value ) ; // needed for IE
9+ /**
10+ * When unselecting an option, setting the property to null / false should be enough
11+ * However, screenreaders might react to the selected attribute instead, see
12+ * https://github.com/angular/angular.js/issues/14419
13+ * Note: "selected" is a boolean attr and will be removed when the "value" arg in attr() is false
14+ * or null
15+ */
16+ optionEl . attr ( 'selected' , value ) ;
17+ }
18+
719/**
820 * @ngdoc type
921 * @name select.SelectController
@@ -44,14 +56,14 @@ var SelectController =
4456 var unknownVal = self . generateUnknownOptionValue ( val ) ;
4557 self . unknownOption . val ( unknownVal ) ;
4658 $element . prepend ( self . unknownOption ) ;
47- setOptionAsSelected ( self . unknownOption ) ;
59+ setOptionSelectedStatus ( self . unknownOption , true ) ;
4860 $element . val ( unknownVal ) ;
4961 } ;
5062
5163 self . updateUnknownOption = function ( val ) {
5264 var unknownVal = self . generateUnknownOptionValue ( val ) ;
5365 self . unknownOption . val ( unknownVal ) ;
54- setOptionAsSelected ( self . unknownOption ) ;
66+ setOptionSelectedStatus ( self . unknownOption , true ) ;
5567 $element . val ( unknownVal ) ;
5668 } ;
5769
@@ -66,7 +78,7 @@ var SelectController =
6678 self . selectEmptyOption = function ( ) {
6779 if ( self . emptyOption ) {
6880 $element . val ( '' ) ;
69- setOptionAsSelected ( self . emptyOption ) ;
81+ setOptionSelectedStatus ( self . emptyOption , true ) ;
7082 }
7183 } ;
7284
@@ -102,7 +114,7 @@ var SelectController =
102114 // Make sure to remove the selected attribute from the previously selected option
103115 // Otherwise, screen readers might get confused
104116 var currentlySelectedOption = $element [ 0 ] . options [ $element [ 0 ] . selectedIndex ] ;
105- if ( currentlySelectedOption ) currentlySelectedOption . removeAttribute ( 'selected' ) ;
117+ if ( currentlySelectedOption ) setOptionSelectedStatus ( jqLite ( currentlySelectedOption ) , false ) ;
106118
107119 if ( self . hasOption ( value ) ) {
108120 self . removeUnknownOption ( ) ;
@@ -112,7 +124,7 @@ var SelectController =
112124
113125 // Set selected attribute and property on selected option for screen readers
114126 var selectedOption = $element [ 0 ] . options [ $element [ 0 ] . selectedIndex ] ;
115- setOptionAsSelected ( jqLite ( selectedOption ) ) ;
127+ setOptionSelectedStatus ( jqLite ( selectedOption ) , true ) ;
116128 } else {
117129 if ( value == null && self . emptyOption ) {
118130 self . removeUnknownOption ( ) ;
@@ -292,11 +304,6 @@ var SelectController =
292304 }
293305 } ) ;
294306 } ;
295-
296- function setOptionAsSelected ( optionEl ) {
297- optionEl . prop ( 'selected' , true ) ; // needed for IE
298- optionEl . attr ( 'selected' , true ) ;
299- }
300307} ] ;
301308
302309/**
@@ -611,11 +618,14 @@ var selectDirective = function() {
611618 includes ( value , selectCtrl . selectValueMap [ option . value ] ) ) ;
612619 var currentlySelected = option . selected ;
613620
614- // IE and Edge will de-select selected options when you set the selected property again, e.g.
615- // when you add to the selection via shift+click/UP/DOWN
616- // Therefore, only set it if necessary
617- if ( ( shouldBeSelected && ! currentlySelected ) || ( ! shouldBeSelected && currentlySelected ) ) {
618- option . selected = shouldBeSelected ;
621+ // IE and Edge, adding options to the selection via shift+click/UP/DOWN,
622+ // will de-select already selected options if "selected" on those options was set
623+ // more than once (i.e. when the options were already selected)
624+ // So we only modify the selected property if neccessary.
625+ // Note: this behavior cannot be replicated via unit tests because it only shows in the
626+ // actual user interface.
627+ if ( shouldBeSelected !== currentlySelected ) {
628+ setOptionSelectedStatus ( jqLite ( option ) , shouldBeSelected ) ;
619629 }
620630
621631 } ) ;
0 commit comments