hammerjs
Version:
A javascript library for multi-touch gestures
258 lines (218 loc) • 7.33 kB
JavaScript
/**
* this holds the last move event,
* used to fix empty touchend issue
* see the onTouch event for an explanation
* @type {Object}
*/
var last_move_event = null;
/**
* when the mouse is hold down, this is true
* @type {Boolean}
*/
var should_detect = false;
/**
* when touch events have been fired, this is true
* @type {Boolean}
*/
var touch_triggered = false;
var Event = Hammer.event = {
/**
* simple addEventListener
* @param {HTMLElement} element
* @param {String} type
* @param {Function} handler
*/
bindDom: function(element, type, handler) {
var types = type.split(' ');
Utils.each(types, function(type){
element.addEventListener(type, handler, false);
});
},
/**
* simple removeEventListener
* @param {HTMLElement} element
* @param {String} type
* @param {Function} handler
*/
unbindDom: function(element, type, handler) {
var types = type.split(' ');
Utils.each(types, function(type){
element.removeEventListener(type, handler, false);
});
},
/**
* touch events with mouse fallback
* @param {HTMLElement} element
* @param {String} eventType like EVENT_MOVE
* @param {Function} handler
*/
onTouch: function onTouch(element, eventType, handler) {
var self = this;
var bindDomOnTouch = function bindDomOnTouch(ev) {
var srcEventType = ev.type.toLowerCase();
// onmouseup, but when touchend has been fired we do nothing.
// this is for touchdevices which also fire a mouseup on touchend
if(Utils.inStr(srcEventType, 'mouse') && touch_triggered) {
return;
}
// mousebutton must be down or a touch event
else if(Utils.inStr(srcEventType, 'touch') || // touch events are always on screen
Utils.inStr(srcEventType, 'pointerdown') || // pointerevents touch
(Utils.inStr(srcEventType, 'mouse') && ev.which === 1) // mouse is pressed
) {
should_detect = true;
}
// mouse isn't pressed
else if(Utils.inStr(srcEventType, 'mouse') && !ev.which) {
should_detect = false;
}
// we are in a touch event, set the touch triggered bool to true,
// this for the conflicts that may occur on ios and android
if(Utils.inStr(srcEventType, 'touch') || Utils.inStr(srcEventType, 'pointer')) {
touch_triggered = true;
}
// count the total touches on the screen
var count_touches = 0;
// when touch has been triggered in this detection session
// and we are now handling a mouse event, we stop that to prevent conflicts
if(should_detect) {
// update pointerevent
if(Hammer.HAS_POINTEREVENTS && eventType != EVENT_END) {
count_touches = PointerEvent.updatePointer(eventType, ev);
}
// touch
else if(Utils.inStr(srcEventType, 'touch')) {
count_touches = ev.touches.length;
}
// mouse
else if(!touch_triggered) {
count_touches = Utils.inStr(srcEventType, 'up') ? 0 : 1;
}
// if we are in a end event, but when we remove one touch and
// we still have enough, set eventType to move
if(count_touches > 0 && eventType == EVENT_END) {
eventType = EVENT_MOVE;
}
// no touches, force the end event
else if(!count_touches) {
eventType = EVENT_END;
}
// store the last move event
if(count_touches || last_move_event === null) {
last_move_event = ev;
}
// trigger the handler
handler.call(Detection, self.collectEventData(element, eventType,
self.getTouchList(last_move_event, eventType),
ev) );
// remove pointerevent from list
if(Hammer.HAS_POINTEREVENTS && eventType == EVENT_END) {
count_touches = PointerEvent.updatePointer(eventType, ev);
}
}
// on the end we reset everything
if(!count_touches) {
last_move_event = null;
should_detect = false;
touch_triggered = false;
PointerEvent.reset();
}
};
this.bindDom(element, Hammer.EVENT_TYPES[eventType], bindDomOnTouch);
// return the bound function to be able to unbind it later
return bindDomOnTouch;
},
/**
* we have different events for each device/browser
* determine what we need and set them in the Hammer.EVENT_TYPES constant
*/
determineEventTypes: function determineEventTypes() {
// determine the eventtype we want to set
var types;
// pointerEvents magic
if(Hammer.HAS_POINTEREVENTS) {
types = PointerEvent.getEvents();
}
// on Android, iOS, blackberry, windows mobile we dont want any mouseevents
else if(Hammer.NO_MOUSEEVENTS) {
types = [
'touchstart',
'touchmove',
'touchend touchcancel'];
}
// for non pointer events browsers and mixed browsers,
// like chrome on windows8 touch laptop
else {
types = [
'touchstart mousedown',
'touchmove mousemove',
'touchend touchcancel mouseup'];
}
Hammer.EVENT_TYPES[EVENT_START] = types[0];
Hammer.EVENT_TYPES[EVENT_MOVE] = types[1];
Hammer.EVENT_TYPES[EVENT_END] = types[2];
},
/**
* create touchlist depending on the event
* @param {Object} ev
* @param {String} eventType used by the fakemultitouch plugin
*/
getTouchList: function getTouchList(ev/*, eventType*/) {
// get the fake pointerEvent touchlist
if(Hammer.HAS_POINTEREVENTS) {
return PointerEvent.getTouchList();
}
// get the touchlist
if(ev.touches) {
return ev.touches;
}
// make fake touchlist from mouse position
ev.identifier = 1;
return [ev];
},
/**
* collect event data for Hammer js
* @param {HTMLElement} element
* @param {String} eventType like EVENT_MOVE
* @param {Object} eventData
*/
collectEventData: function collectEventData(element, eventType, touches, ev) {
// find out pointerType
var pointerType = POINTER_TOUCH;
if(Utils.inStr(ev.type, 'mouse') || PointerEvent.matchType(POINTER_MOUSE, ev)) {
pointerType = POINTER_MOUSE;
}
return {
center : Utils.getCenter(touches),
timeStamp : Date.now(),
target : ev.target,
touches : touches,
eventType : eventType,
pointerType: pointerType,
srcEvent : ev,
/**
* prevent the browser default actions
* mostly used to disable scrolling of the browser
*/
preventDefault: function() {
var srcEvent = this.srcEvent;
srcEvent.preventManipulation && srcEvent.preventManipulation();
srcEvent.preventDefault && srcEvent.preventDefault();
},
/**
* stop bubbling the event up to its parents
*/
stopPropagation: function() {
this.srcEvent.stopPropagation();
},
/**
* immediately stop gesture detection
* might be useful after a swipe was detected
* @return {*}
*/
stopDetect: function() {
return Detection.stopDetect();
}
};
}
};