@@ -954,6 +954,115 @@ describe('$aria', function() {
954954 expect ( clickEvents ) . toEqual ( [ 'div(true)' , 'li(true)' , 'div(true)' , 'li(true)' ] ) ;
955955 } ) ;
956956
957+ it ( 'should trigger a click in browsers that provide `event.which` instead of `event.keyCode`' ,
958+ function ( ) {
959+ compileElement (
960+ '<section>' +
961+ '<div ng-click="onClick($event)"></div>' +
962+ '<ul><li ng-click="onClick($event)"></li></ul>' +
963+ '</section>' ) ;
964+
965+ var divElement = element . find ( 'div' ) ;
966+ var liElement = element . find ( 'li' ) ;
967+
968+ divElement . triggerHandler ( { type : 'keydown' , which : 13 } ) ;
969+ liElement . triggerHandler ( { type : 'keydown' , which : 13 } ) ;
970+ divElement . triggerHandler ( { type : 'keydown' , which : 32 } ) ;
971+ liElement . triggerHandler ( { type : 'keydown' , which : 32 } ) ;
972+
973+ expect ( clickEvents ) . toEqual ( [ 'div(true)' , 'li(true)' , 'div(true)' , 'li(true)' ] ) ;
974+ }
975+ ) ;
976+
977+ it ( 'should not prevent default keyboard action if the target element has editable content' ,
978+ inject ( function ( $document ) {
979+ // Note:
980+ // `contenteditable` is an enumarated (not a boolean) attribute (see
981+ // https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/contenteditable).
982+ // We need to check the following conditions:
983+ // - No attribute.
984+ // - Value: ""
985+ // - Value: "true"
986+ // - Value: "false"
987+
988+ function eventFor ( keyCode ) {
989+ return { bubbles : true , cancelable : true , keyCode : keyCode } ;
990+ }
991+
992+ compileElement (
993+ '<section>' +
994+ // No attribute.
995+ '<div id="no-attribute">' +
996+ '<div ng-click="onClick($event)"></div>' +
997+ '<ul ng-click="onClick($event)"><li></li></ul>' +
998+ '</div>' +
999+
1000+ // Value: ""
1001+ '<div id="value-empty">' +
1002+ '<div ng-click="onClick($event)" contenteditable=""></div>' +
1003+ '<ul ng-click="onClick($event)"><li contenteditable=""></li></ul>' +
1004+ '</div>' +
1005+
1006+ // Value: "true"
1007+ '<div id="value-true">' +
1008+ '<div ng-click="onClick($event)" contenteditable="true"></div>' +
1009+ '<ul ng-click="onClick($event)"><li contenteditable="true"></li></ul>' +
1010+ '</div>' +
1011+
1012+ // Value: "false"
1013+ '<div id="value-false">' +
1014+ '<div ng-click="onClick($event)" contenteditable="false"></div>' +
1015+ '<ul ng-click="onClick($event)"><li contenteditable="false"></li></ul>' +
1016+ '</div>' +
1017+ '</section>' ) ;
1018+
1019+ // Support: Safari 11-12+
1020+ // Attach to DOM, because otherwise Safari will not update the `isContentEditable` property
1021+ // based on the `contenteditable` attribute.
1022+ $document . find ( 'body' ) . append ( element ) ;
1023+
1024+ var containers = element . children ( ) ;
1025+ var container ;
1026+
1027+ // Using `browserTrigger()`, because it supports event bubbling.
1028+
1029+ // No attribute | Elements are not editable.
1030+ container = containers . eq ( 0 ) ;
1031+ browserTrigger ( container . find ( 'div' ) , 'keydown' , eventFor ( 13 ) ) ;
1032+ browserTrigger ( container . find ( 'ul' ) , 'keydown' , eventFor ( 32 ) ) ;
1033+ browserTrigger ( container . find ( 'li' ) , 'keydown' , eventFor ( 13 ) ) ;
1034+
1035+ expect ( clickEvents ) . toEqual ( [ 'div(true)' , 'ul(true)' , 'li(true)' ] ) ;
1036+
1037+ // Value: "" | Elements are editable.
1038+ clickEvents = [ ] ;
1039+ container = containers . eq ( 1 ) ;
1040+ browserTrigger ( container . find ( 'div' ) , 'keydown' , eventFor ( 32 ) ) ;
1041+ browserTrigger ( container . find ( 'ul' ) , 'keydown' , eventFor ( 13 ) ) ;
1042+ browserTrigger ( container . find ( 'li' ) , 'keydown' , eventFor ( 32 ) ) ;
1043+
1044+ expect ( clickEvents ) . toEqual ( [ 'div(false)' , 'ul(true)' , 'li(false)' ] ) ;
1045+
1046+ // Value: "true" | Elements are editable.
1047+ clickEvents = [ ] ;
1048+ container = containers . eq ( 2 ) ;
1049+ browserTrigger ( container . find ( 'div' ) , 'keydown' , eventFor ( 13 ) ) ;
1050+ browserTrigger ( container . find ( 'ul' ) , 'keydown' , eventFor ( 32 ) ) ;
1051+ browserTrigger ( container . find ( 'li' ) , 'keydown' , eventFor ( 13 ) ) ;
1052+
1053+ expect ( clickEvents ) . toEqual ( [ 'div(false)' , 'ul(true)' , 'li(false)' ] ) ;
1054+
1055+ // Value: "false" | Elements are not editable.
1056+ clickEvents = [ ] ;
1057+ container = containers . eq ( 3 ) ;
1058+ browserTrigger ( container . find ( 'div' ) , 'keydown' , eventFor ( 32 ) ) ;
1059+ browserTrigger ( container . find ( 'ul' ) , 'keydown' , eventFor ( 13 ) ) ;
1060+ browserTrigger ( container . find ( 'li' ) , 'keydown' , eventFor ( 32 ) ) ;
1061+
1062+ expect ( clickEvents ) . toEqual ( [ 'div(true)' , 'ul(true)' , 'li(true)' ] ) ;
1063+ } )
1064+ ) ;
1065+
9571066 they ( 'should not prevent default keyboard action if an interactive $type element' +
9581067 'is nested inside ng-click' , nodeBlackList , function ( elementType ) {
9591068 function createHTML ( type ) {
@@ -981,26 +1090,6 @@ describe('$aria', function() {
9811090 }
9821091 ) ;
9831092
984- it ( 'should trigger a click in browsers that provide `event.which` instead of `event.keyCode`' ,
985- function ( ) {
986- compileElement (
987- '<section>' +
988- '<div ng-click="onClick($event)"></div>' +
989- '<ul><li ng-click="onClick($event)"></li></ul>' +
990- '</section>' ) ;
991-
992- var divElement = element . find ( 'div' ) ;
993- var liElement = element . find ( 'li' ) ;
994-
995- divElement . triggerHandler ( { type : 'keydown' , which : 13 } ) ;
996- liElement . triggerHandler ( { type : 'keydown' , which : 13 } ) ;
997- divElement . triggerHandler ( { type : 'keydown' , which : 32 } ) ;
998- liElement . triggerHandler ( { type : 'keydown' , which : 32 } ) ;
999-
1000- expect ( clickEvents ) . toEqual ( [ 'div(true)' , 'li(true)' , 'div(true)' , 'li(true)' ] ) ;
1001- }
1002- ) ;
1003-
10041093 they ( 'should not bind to key events if there is existing `ng-$prop`' ,
10051094 [ 'keydown' , 'keypress' , 'keyup' ] , function ( eventName ) {
10061095 scope . onKeyEvent = jasmine . createSpy ( 'onKeyEvent' ) ;
0 commit comments