@@ -38,6 +38,7 @@ import {
38
38
SCROLL_THROTTLE_MS ,
39
39
TOOLTIP_PANEL_CLASS ,
40
40
MAT_TOOLTIP_DEFAULT_OPTIONS ,
41
+ TooltipTouchGestures ,
41
42
} from './index' ;
42
43
43
44
@@ -895,33 +896,175 @@ describe('MatTooltip', () => {
895
896
} ) ) ;
896
897
} ) ;
897
898
898
- describe ( 'special cases' , ( ) => {
899
+ describe ( 'touch gestures' , ( ) => {
900
+ beforeEach ( ( ) => {
901
+ platform . ANDROID = true ;
902
+ } ) ;
903
+
904
+ it ( 'should have a delay when showing on touchstart' , fakeAsync ( ( ) => {
905
+ const fixture = TestBed . createComponent ( BasicTooltipDemo ) ;
906
+ fixture . detectChanges ( ) ;
907
+ const button : HTMLButtonElement = fixture . nativeElement . querySelector ( 'button' ) ;
908
+
909
+ dispatchFakeEvent ( button , 'touchstart' ) ;
910
+ fixture . detectChanges ( ) ;
911
+ tick ( 250 ) ; // Halfway through the delay.
912
+
913
+ assertTooltipInstance ( fixture . componentInstance . tooltip , false ) ;
914
+
915
+ tick ( 250 ) ; // Finish the delay.
916
+ fixture . detectChanges ( ) ;
917
+ tick ( 500 ) ; // Finish the animation.
918
+
919
+ assertTooltipInstance ( fixture . componentInstance . tooltip , true ) ;
920
+ } ) ) ;
921
+
922
+ it ( 'should be able to disable opening on touch' , fakeAsync ( ( ) => {
923
+ const fixture = TestBed . createComponent ( BasicTooltipDemo ) ;
924
+ fixture . componentInstance . touchGestures = 'off' ;
925
+ fixture . detectChanges ( ) ;
926
+ const button : HTMLButtonElement = fixture . nativeElement . querySelector ( 'button' ) ;
927
+
928
+ dispatchFakeEvent ( button , 'touchstart' ) ;
929
+ fixture . detectChanges ( ) ;
930
+ tick ( 500 ) ; // Finish the delay.
931
+ fixture . detectChanges ( ) ;
932
+ tick ( 500 ) ; // Finish the animation.
933
+
934
+ assertTooltipInstance ( fixture . componentInstance . tooltip , false ) ;
935
+ } ) ) ;
936
+
937
+ it ( 'should not prevent the default action on touchstart' , ( ) => {
938
+ const fixture = TestBed . createComponent ( BasicTooltipDemo ) ;
939
+ fixture . detectChanges ( ) ;
940
+ const button : HTMLButtonElement = fixture . nativeElement . querySelector ( 'button' ) ;
941
+ const event = dispatchFakeEvent ( button , 'touchstart' ) ;
942
+ fixture . detectChanges ( ) ;
943
+
944
+ expect ( event . defaultPrevented ) . toBe ( false ) ;
945
+ } ) ;
946
+
947
+ it ( 'should close on touchend with a delay' , fakeAsync ( ( ) => {
948
+ const fixture = TestBed . createComponent ( BasicTooltipDemo ) ;
949
+ fixture . detectChanges ( ) ;
950
+ const button : HTMLButtonElement = fixture . nativeElement . querySelector ( 'button' ) ;
951
+
952
+ dispatchFakeEvent ( button , 'touchstart' ) ;
953
+ fixture . detectChanges ( ) ;
954
+ tick ( 500 ) ; // Finish the open delay.
955
+ fixture . detectChanges ( ) ;
956
+ tick ( 500 ) ; // Finish the animation.
957
+ assertTooltipInstance ( fixture . componentInstance . tooltip , true ) ;
958
+
959
+ dispatchFakeEvent ( button , 'touchend' ) ;
960
+ fixture . detectChanges ( ) ;
961
+ tick ( 1000 ) ; // 2/3 through the delay
962
+ assertTooltipInstance ( fixture . componentInstance . tooltip , true ) ;
963
+
964
+ tick ( 500 ) ; // Finish the delay.
965
+ fixture . detectChanges ( ) ;
966
+ tick ( 500 ) ; // Finish the exit animation.
899
967
900
- it ( 'should clear the `user-select` when a tooltip is set on a text field' , ( ) => {
968
+ assertTooltipInstance ( fixture . componentInstance . tooltip , false ) ;
969
+ } ) ) ;
970
+
971
+ it ( 'should close on touchcancel with a delay' , fakeAsync ( ( ) => {
972
+ const fixture = TestBed . createComponent ( BasicTooltipDemo ) ;
973
+ fixture . detectChanges ( ) ;
974
+ const button : HTMLButtonElement = fixture . nativeElement . querySelector ( 'button' ) ;
975
+
976
+ dispatchFakeEvent ( button , 'touchstart' ) ;
977
+ fixture . detectChanges ( ) ;
978
+ tick ( 500 ) ; // Finish the open delay.
979
+ fixture . detectChanges ( ) ;
980
+ tick ( 500 ) ; // Finish the animation.
981
+ assertTooltipInstance ( fixture . componentInstance . tooltip , true ) ;
982
+
983
+ dispatchFakeEvent ( button , 'touchcancel' ) ;
984
+ fixture . detectChanges ( ) ;
985
+ tick ( 1000 ) ; // 2/3 through the delay
986
+ assertTooltipInstance ( fixture . componentInstance . tooltip , true ) ;
987
+
988
+ tick ( 500 ) ; // Finish the delay.
989
+ fixture . detectChanges ( ) ;
990
+ tick ( 500 ) ; // Finish the exit animation.
991
+
992
+ assertTooltipInstance ( fixture . componentInstance . tooltip , false ) ;
993
+ } ) ) ;
994
+
995
+ it ( 'should disable native touch interactions' , ( ) => {
996
+ const fixture = TestBed . createComponent ( BasicTooltipDemo ) ;
997
+ fixture . detectChanges ( ) ;
998
+
999
+ const styles = fixture . nativeElement . querySelector ( 'button' ) . style ;
1000
+ expect ( styles . touchAction || ( styles as any ) . webkitUserDrag ) . toBe ( 'none' ) ;
1001
+ } ) ;
1002
+
1003
+ it ( 'should allow native touch interactions if touch gestures are turned off' , ( ) => {
1004
+ const fixture = TestBed . createComponent ( BasicTooltipDemo ) ;
1005
+ fixture . componentInstance . touchGestures = 'off' ;
1006
+ fixture . detectChanges ( ) ;
1007
+
1008
+ const styles = fixture . nativeElement . querySelector ( 'button' ) . style ;
1009
+ expect ( styles . touchAction || ( styles as any ) . webkitUserDrag ) . toBeFalsy ( ) ;
1010
+ } ) ;
1011
+
1012
+ it ( 'should allow text selection on inputs when gestures are set to auto' , ( ) => {
901
1013
const fixture = TestBed . createComponent ( TooltipOnTextFields ) ;
902
- const instance = fixture . componentInstance ;
1014
+ fixture . detectChanges ( ) ;
1015
+
1016
+ const inputStyle = fixture . componentInstance . input . nativeElement . style ;
1017
+ const textareaStyle = fixture . componentInstance . textarea . nativeElement . style ;
1018
+
1019
+ expect ( inputStyle . userSelect ) . toBeFalsy ( ) ;
1020
+ expect ( inputStyle . webkitUserSelect ) . toBeFalsy ( ) ;
1021
+ expect ( inputStyle . msUserSelect ) . toBeFalsy ( ) ;
1022
+ expect ( ( inputStyle as any ) . MozUserSelect ) . toBeFalsy ( ) ;
1023
+
1024
+ expect ( textareaStyle . userSelect ) . toBeFalsy ( ) ;
1025
+ expect ( textareaStyle . webkitUserSelect ) . toBeFalsy ( ) ;
1026
+ expect ( textareaStyle . msUserSelect ) . toBeFalsy ( ) ;
1027
+ expect ( ( textareaStyle as any ) . MozUserSelect ) . toBeFalsy ( ) ;
1028
+ } ) ;
903
1029
1030
+ it ( 'should disable text selection on inputs when gestures are set to on' , ( ) => {
1031
+ const fixture = TestBed . createComponent ( TooltipOnTextFields ) ;
1032
+ fixture . componentInstance . touchGestures = 'on' ;
904
1033
fixture . detectChanges ( ) ;
905
1034
906
- expect ( instance . input . nativeElement . style . userSelect ) . toBeFalsy ( ) ;
907
- expect ( instance . input . nativeElement . style . webkitUserSelect ) . toBeFalsy ( ) ;
908
- expect ( instance . input . nativeElement . style . msUserSelect ) . toBeFalsy ( ) ;
1035
+ const inputStyle = fixture . componentInstance . input . nativeElement . style ;
1036
+ const inputUserSelect = inputStyle . userSelect || inputStyle . webkitUserSelect ||
1037
+ inputStyle . msUserSelect || ( inputStyle as any ) . MozUserSelect ;
1038
+ const textareaStyle = fixture . componentInstance . textarea . nativeElement . style ;
1039
+ const textareaUserSelect = textareaStyle . userSelect || textareaStyle . webkitUserSelect ||
1040
+ textareaStyle . msUserSelect || ( textareaStyle as any ) . MozUserSelect ;
909
1041
910
- expect ( instance . textarea . nativeElement . style . userSelect ) . toBeFalsy ( ) ;
911
- expect ( instance . textarea . nativeElement . style . webkitUserSelect ) . toBeFalsy ( ) ;
912
- expect ( instance . textarea . nativeElement . style . msUserSelect ) . toBeFalsy ( ) ;
1042
+ expect ( inputUserSelect ) . toBe ( 'none' ) ;
1043
+ expect ( textareaUserSelect ) . toBe ( 'none' ) ;
913
1044
} ) ;
914
1045
915
- it ( 'should clear the `-webkit-user-drag` on draggable elements' , ( ) => {
1046
+ it ( 'should allow native dragging on draggable elements when gestures are set to auto ' , ( ) => {
916
1047
const fixture = TestBed . createComponent ( TooltipOnDraggableElement ) ;
917
-
918
1048
fixture . detectChanges ( ) ;
919
1049
920
1050
expect ( fixture . componentInstance . button . nativeElement . style . webkitUserDrag ) . toBeFalsy ( ) ;
921
1051
} ) ;
922
1052
1053
+ it ( 'should disable native dragging on draggable elements when gestures are set to on' , ( ) => {
1054
+ const fixture = TestBed . createComponent ( TooltipOnDraggableElement ) ;
1055
+ fixture . componentInstance . touchGestures = 'on' ;
1056
+ fixture . detectChanges ( ) ;
1057
+
1058
+ const styles = fixture . componentInstance . button . nativeElement . style ;
1059
+
1060
+ if ( 'webkitUserDrag' in styles ) {
1061
+ expect ( styles . webkitUserDrag ) . toBe ( 'none' ) ;
1062
+ }
1063
+ } ) ;
1064
+
923
1065
it ( 'should not open on `mouseenter` on iOS' , ( ) => {
924
1066
platform . IOS = true ;
1067
+ platform . ANDROID = false ;
925
1068
926
1069
const fixture = TestBed . createComponent ( BasicTooltipDemo ) ;
927
1070
@@ -934,6 +1077,7 @@ describe('MatTooltip', () => {
934
1077
935
1078
it ( 'should not open on `mouseenter` on Android' , ( ) => {
936
1079
platform . ANDROID = true ;
1080
+ platform . IOS = false ;
937
1081
938
1082
const fixture = TestBed . createComponent ( BasicTooltipDemo ) ;
939
1083
@@ -943,7 +1087,6 @@ describe('MatTooltip', () => {
943
1087
944
1088
assertTooltipInstance ( fixture . componentInstance . tooltip , false ) ;
945
1089
} ) ;
946
-
947
1090
} ) ;
948
1091
949
1092
} ) ;
@@ -955,7 +1098,8 @@ describe('MatTooltip', () => {
955
1098
*ngIf="showButton"
956
1099
[matTooltip]="message"
957
1100
[matTooltipPosition]="position"
958
- [matTooltipClass]="{'custom-one': showTooltipClass, 'custom-two': showTooltipClass }">
1101
+ [matTooltipClass]="{'custom-one': showTooltipClass, 'custom-two': showTooltipClass }"
1102
+ [matTooltipTouchGestures]="touchGestures">
959
1103
Button
960
1104
</button>`
961
1105
} )
@@ -964,6 +1108,7 @@ class BasicTooltipDemo {
964
1108
message : any = initialTooltipMessage ;
965
1109
showButton : boolean = true ;
966
1110
showTooltipClass = false ;
1111
+ touchGestures : TooltipTouchGestures = 'auto' ;
967
1112
@ViewChild ( MatTooltip , { static : false } ) tooltip : MatTooltip ;
968
1113
@ViewChild ( 'button' , { static : false } ) button : ElementRef < HTMLButtonElement > ;
969
1114
}
@@ -1037,31 +1182,33 @@ class DataBoundAriaLabelTooltip {
1037
1182
template : `
1038
1183
<input
1039
1184
#input
1040
- style="user-select: none; -webkit-user-select: none "
1041
- matTooltip="Something ">
1185
+ matTooltip="Something "
1186
+ [matTooltipTouchGestures]="touchGestures ">
1042
1187
1043
1188
<textarea
1044
1189
#textarea
1045
- style="user-select: none; -webkit-user-select: none "
1046
- matTooltip="Another thing "></textarea>
1190
+ matTooltip="Another thing "
1191
+ [matTooltipTouchGestures]="touchGestures "></textarea>
1047
1192
` ,
1048
1193
} )
1049
1194
class TooltipOnTextFields {
1050
1195
@ViewChild ( 'input' , { static : false } ) input : ElementRef < HTMLInputElement > ;
1051
1196
@ViewChild ( 'textarea' , { static : false } ) textarea : ElementRef < HTMLTextAreaElement > ;
1197
+ touchGestures : TooltipTouchGestures = 'auto' ;
1052
1198
}
1053
1199
1054
1200
@Component ( {
1055
1201
template : `
1056
1202
<button
1057
1203
#button
1058
- style="-webkit-user-drag: none;"
1059
1204
draggable="true"
1060
- matTooltip="Drag me"></button>
1205
+ matTooltip="Drag me"
1206
+ [matTooltipTouchGestures]="touchGestures"></button>
1061
1207
` ,
1062
1208
} )
1063
1209
class TooltipOnDraggableElement {
1064
1210
@ViewChild ( 'button' , { static : false } ) button : ElementRef ;
1211
+ touchGestures : TooltipTouchGestures = 'auto' ;
1065
1212
}
1066
1213
1067
1214
@Component ( {
0 commit comments