angular-material-npfixed
Version:
The Angular Material project is an implementation of Material Design in Angular.js. This project provides a set of reusable, well-tested, and accessible Material Design UI components. Angular Material is supported internally at Google by the Angular.js, M
150 lines (127 loc) • 4.5 kB
JavaScript
/**
* @ngdoc module
* @name material.core.interaction
* @description
* User interaction detection to provide proper accessibility.
*/
angular
.module('material.core.interaction', [])
.service('$mdInteraction', MdInteractionService);
/**
* @ngdoc service
* @name $mdInteraction
* @module material.core.interaction
*
* @description
*
* Service which keeps track of the last interaction type and validates them for several browsers.
* The service hooks into the document's body and listens for touch, mouse and keyboard events.
*
* The most recent interaction type can be retrieved by calling the `getLastInteractionType` method.
*
* Here is an example markup for using the interaction service.
*
* <hljs lang="js">
* var lastType = $mdInteraction.getLastInteractionType();
*
* if (lastType === 'keyboard') {
* // We only restore the focus for keyboard users.
* restoreFocus();
* }
* </hljs>
*
*/
function MdInteractionService($timeout, $mdUtil) {
this.$timeout = $timeout;
this.$mdUtil = $mdUtil;
this.bodyElement = angular.element(document.body);
this.isBuffering = false;
this.bufferTimeout = null;
this.lastInteractionType = null;
this.lastInteractionTime = null;
// Type Mappings for the different events
// There will be three three interaction types
// `keyboard`, `mouse` and `touch`
// type `pointer` will be evaluated in `pointerMap` for IE Browser events
this.inputEventMap = {
'keydown': 'keyboard',
'mousedown': 'mouse',
'mouseenter': 'mouse',
'touchstart': 'touch',
'pointerdown': 'pointer',
'MSPointerDown': 'pointer'
};
// IE PointerDown events will be validated in `touch` or `mouse`
// Index numbers referenced here: https://msdn.microsoft.com/library/windows/apps/hh466130.aspx
this.iePointerMap = {
2: 'touch',
3: 'touch',
4: 'mouse'
};
this.initializeEvents();
}
/**
* Initializes the interaction service, by registering all interaction events to the
* body element.
*/
MdInteractionService.prototype.initializeEvents = function() {
// IE browsers can also trigger pointer events, which also leads to an interaction.
var pointerEvent = 'MSPointerEvent' in window ? 'MSPointerDown' : 'PointerEvent' in window ? 'pointerdown' : null;
this.bodyElement.on('keydown mousedown', this.onInputEvent.bind(this));
if ('ontouchstart' in document.documentElement) {
this.bodyElement.on('touchstart', this.onBufferInputEvent.bind(this));
}
if (pointerEvent) {
this.bodyElement.on(pointerEvent, this.onInputEvent.bind(this));
}
};
/**
* Event listener for normal interaction events, which should be tracked.
* @param event {MouseEvent|KeyboardEvent|PointerEvent|TouchEvent}
*/
MdInteractionService.prototype.onInputEvent = function(event) {
if (this.isBuffering) {
return;
}
var type = this.inputEventMap[event.type];
if (type === 'pointer') {
type = this.iePointerMap[event.pointerType] || event.pointerType;
}
this.lastInteractionType = type;
this.lastInteractionTime = this.$mdUtil.now();
};
/**
* Event listener for interaction events which should be buffered (touch events).
* @param event {TouchEvent}
*/
MdInteractionService.prototype.onBufferInputEvent = function(event) {
this.$timeout.cancel(this.bufferTimeout);
this.onInputEvent(event);
this.isBuffering = true;
// The timeout of 650ms is needed to delay the touchstart, because otherwise the touch will call
// the `onInput` function multiple times.
this.bufferTimeout = this.$timeout(function() {
this.isBuffering = false;
}.bind(this), 650, false);
};
/**
* @ngdoc method
* @name $mdInteraction#getLastInteractionType
* @description Retrieves the last interaction type triggered in body.
* @returns {string|null} Last interaction type.
*/
MdInteractionService.prototype.getLastInteractionType = function() {
return this.lastInteractionType;
};
/**
* @ngdoc method
* @name $mdInteraction#isUserInvoked
* @description Method to detect whether any interaction happened recently or not.
* @param {number=} checkDelay Time to check for any interaction to have been triggered.
* @returns {boolean} Whether there was any interaction or not.
*/
MdInteractionService.prototype.isUserInvoked = function(checkDelay) {
var delay = angular.isNumber(checkDelay) ? checkDelay : 15;
// Check for any interaction to be within the specified check time.
return this.lastInteractionTime >= this.$mdUtil.now() - delay;
};