1
+ /*
2
+ * @ngdoc module
3
+ * @name material.core.interaction
4
+ * @description
5
+ * User interaction detection to provide proper accessibility.
6
+ */
1
7
angular
2
8
. module ( 'material.core.interaction' , [ ] )
3
9
. service ( '$mdInteraction' , MdInteractionService ) ;
4
10
11
+
5
12
/*
6
13
* @ngdoc service
7
14
* @name $mdInteraction
@@ -12,33 +19,33 @@ angular
12
19
* Service which keeps track of the last interaction type and validates them for several browsers.
13
20
* The service hooks into the document's body and listens for touch, mouse and keyboard events.
14
21
*
15
- * The last interaction type can be retrieved by using the `getLastInteractionType` method, which returns
16
- * the following possible values:
17
- * - `touch`
18
- * - `mouse`
19
- * - `keyboard`
22
+ * The most recent interaction type can be retrieved by calling the `getLastInteractionType` method.
20
23
*
21
24
* Here is an example markup for using the interaction service.
22
- * ```
25
+ *
26
+ * <hljs lang="js">
23
27
* var lastType = $mdInteraction.getLastInteractionType();
28
+ *
24
29
* if (lastType === 'keyboard') {
30
+ * // We only restore the focus for keyboard users.
25
31
* restoreFocus();
26
- * }}
27
- * ```
32
+ * }
33
+ * </hljs>
28
34
*
29
35
*/
30
36
function MdInteractionService ( $timeout ) {
31
- var body = angular . element ( document . body ) ;
32
- var mouseEvent = window . MSPointerEvent ? 'MSPointerDown' : window . PointerEvent ? 'pointerdown' : 'mousedown' ;
33
- var buffer = false ;
34
- var timer ;
35
- var lastInteractionType ;
37
+ this . $timeout = $timeout ;
38
+
39
+ this . bodyElement = angular . element ( document . body ) ;
40
+ this . isBuffering = false ;
41
+ this . bufferTimeout = null ;
42
+ this . lastInteractionType = null ;
36
43
37
44
// Type Mappings for the different events
38
45
// There will be three three interaction types
39
46
// `keyboard`, `mouse` and `touch`
40
47
// type `pointer` will be evaluated in `pointerMap` for IE Browser events
41
- var inputMap = {
48
+ this . inputEventMap = {
42
49
'keydown' : 'keyboard' ,
43
50
'mousedown' : 'mouse' ,
44
51
'mouseenter' : 'mouse' ,
@@ -49,47 +56,77 @@ function MdInteractionService($timeout) {
49
56
50
57
// IE PointerDown events will be validated in `touch` or `mouse`
51
58
// Index numbers referenced here: https://msdn.microsoft.com/library/windows/apps/hh466130.aspx
52
- var pointerMap = {
59
+ this . iePointerMap = {
53
60
2 : 'touch' ,
54
61
3 : 'touch' ,
55
62
4 : 'mouse'
56
63
} ;
57
64
58
- function onInput ( event ) {
59
- if ( buffer ) return ;
60
- var type = inputMap [ event . type ] ;
61
- if ( type === 'pointer' ) {
62
- type = ( typeof event . pointerType === 'number' ) ? pointerMap [ event . pointerType ] : event . pointerType ;
63
- }
64
- lastInteractionType = type ;
65
- }
65
+ this . initializeEvents ( ) ;
66
+ }
66
67
67
- function onBufferInput ( event ) {
68
- $timeout . cancel ( timer ) ;
68
+ /**
69
+ * Initializes the interaction service, by registering all interaction events to the
70
+ * body element.
71
+ */
72
+ MdInteractionService . prototype . initializeEvents = function ( ) {
73
+ // IE browsers can also trigger pointer events, which also leads to an interaction.
74
+ var pointerEvent = 'MSPointerEvent' in window ? 'MSPointerDown' : 'PointerEvent' in window ? 'pointerdown' : null ;
69
75
70
- onInput ( event ) ;
71
- buffer = true ;
76
+ this . bodyElement . on ( 'keydown mousedown' , this . onInputEvent . bind ( this ) ) ;
72
77
73
- // The timeout of 650ms is needed to delay the touchstart, because otherwise the touch will call
74
- // the `onInput` function multiple times.
75
- timer = $timeout ( function ( ) {
76
- buffer = false ;
77
- } , 650 , false ) ;
78
+ if ( 'ontouchstart' in document . documentElement ) {
79
+ this . bodyElement . on ( 'touchstart' , this . onBufferInputEvent . bind ( this ) ) ;
78
80
}
79
81
80
- body . on ( 'keydown' , onInput ) ;
81
- body . on ( mouseEvent , onInput ) ;
82
- body . on ( 'mouseenter' , onInput ) ;
83
- if ( 'ontouchstart' in document . documentElement ) {
84
- body . on ( 'touchstart' , onBufferInput ) ;
82
+ if ( pointerEvent ) {
83
+ this . bodyElement . on ( pointerEvent , this . onInputEvent . bind ( this ) ) ;
84
+ }
85
+
86
+ } ;
87
+
88
+ /**
89
+ * Event listener for normal interaction events, which should be tracked.
90
+ * @param event {MouseEvent|KeyboardEvent|PointerEvent}
91
+ */
92
+ MdInteractionService . prototype . onInputEvent = function ( event ) {
93
+ if ( this . isBuffering ) {
94
+ return ;
85
95
}
86
96
87
- /**
88
- * Gets the last interaction type triggered in body.
89
- * Possible return values are `mouse`, `keyboard` and `touch`
90
- * @returns {string }
91
- */
92
- this . getLastInteractionType = function ( ) {
93
- return lastInteractionType ;
97
+ var type = this . inputEventMap [ event . type ] ;
98
+
99
+ if ( type === 'pointer' ) {
100
+ type = this . iePointerMap [ event . pointerType ] || event . pointerType ;
94
101
}
95
- }
102
+
103
+ this . lastInteractionType = type ;
104
+ } ;
105
+
106
+ /**
107
+ * Event listener for interaction events which should be buffered (touch events).
108
+ * @param event {TouchEvent}
109
+ */
110
+ MdInteractionService . prototype . onBufferInputEvent = function ( event ) {
111
+ this . $timeout . cancel ( this . bufferTimeout ) ;
112
+
113
+ this . onInputEvent ( event ) ;
114
+ this . isBuffering = true ;
115
+
116
+ // The timeout of 650ms is needed to delay the touchstart, because otherwise the touch will call
117
+ // the `onInput` function multiple times.
118
+ this . bufferTimeout = this . $timeout ( function ( ) {
119
+ this . isBuffering = false ;
120
+ } . bind ( this ) , 650 , false ) ;
121
+
122
+ } ;
123
+
124
+ /**
125
+ * @ngdoc method
126
+ * @name $mdInteraction#getLastInteractionType
127
+ * @description Retrieves the last interaction type triggered in body.
128
+ * @returns {'mouse'|'keyboard'|'touch' } Last interaction type.
129
+ */
130
+ MdInteractionService . prototype . getLastInteractionType = function ( ) {
131
+ return this . lastInteractionType ;
132
+ } ;
0 commit comments