1+ /**
2+ * @ngdoc module
3+ * @name material.core.interaction
4+ * @description
5+ * User interaction detection to provide proper accessibility.
6+ */
7+ angular
8+ . module ( 'material.core.interaction' , [ ] )
9+ . service ( '$mdInteraction' , MdInteractionService ) ;
10+
11+
12+ /**
13+ * @ngdoc service
14+ * @name $mdInteraction
15+ * @module material.core.interaction
16+ *
17+ * @description
18+ *
19+ * Service which keeps track of the last interaction type and validates them for several browsers.
20+ * The service hooks into the document's body and listens for touch, mouse and keyboard events.
21+ *
22+ * The most recent interaction type can be retrieved by calling the `getLastInteractionType` method.
23+ *
24+ * Here is an example markup for using the interaction service.
25+ *
26+ * <hljs lang="js">
27+ * var lastType = $mdInteraction.getLastInteractionType();
28+ *
29+ * if (lastType === 'keyboard') {
30+ * // We only restore the focus for keyboard users.
31+ * restoreFocus();
32+ * }
33+ * </hljs>
34+ *
35+ */
36+ function MdInteractionService ( $timeout ) {
37+ this . $timeout = $timeout ;
38+
39+ this . bodyElement = angular . element ( document . body ) ;
40+ this . isBuffering = false ;
41+ this . bufferTimeout = null ;
42+ this . lastInteractionType = null ;
43+
44+ // Type Mappings for the different events
45+ // There will be three three interaction types
46+ // `keyboard`, `mouse` and `touch`
47+ // type `pointer` will be evaluated in `pointerMap` for IE Browser events
48+ this . inputEventMap = {
49+ 'keydown' : 'keyboard' ,
50+ 'mousedown' : 'mouse' ,
51+ 'mouseenter' : 'mouse' ,
52+ 'touchstart' : 'touch' ,
53+ 'pointerdown' : 'pointer' ,
54+ 'MSPointerDown' : 'pointer'
55+ } ;
56+
57+ // IE PointerDown events will be validated in `touch` or `mouse`
58+ // Index numbers referenced here: https://msdn.microsoft.com/library/windows/apps/hh466130.aspx
59+ this . iePointerMap = {
60+ 2 : 'touch' ,
61+ 3 : 'touch' ,
62+ 4 : 'mouse'
63+ } ;
64+
65+ this . initializeEvents ( ) ;
66+ }
67+
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 ;
75+
76+ this . bodyElement . on ( 'keydown mousedown' , this . onInputEvent . bind ( this ) ) ;
77+
78+ if ( 'ontouchstart' in document . documentElement ) {
79+ this . bodyElement . on ( 'touchstart' , this . onBufferInputEvent . bind ( this ) ) ;
80+ }
81+
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 ;
95+ }
96+
97+ var type = this . inputEventMap [ event . type ] ;
98+
99+ if ( type === 'pointer' ) {
100+ type = this . iePointerMap [ event . pointerType ] || event . pointerType ;
101+ }
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 {string|null } Last interaction type.
129+ */
130+ MdInteractionService . prototype . getLastInteractionType = function ( ) {
131+ return this . lastInteractionType ;
132+ } ;
0 commit comments