Skip to content

Commit

Permalink
more code
Browse files Browse the repository at this point in the history
  • Loading branch information
jtangelder committed May 22, 2014
1 parent b6a8914 commit 712f5f6
Show file tree
Hide file tree
Showing 13 changed files with 342 additions and 99 deletions.
3 changes: 1 addition & 2 deletions Gruntfile.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,9 @@ module.exports = (grunt) ->
banner: '<%= meta.banner %>'
src: [
'src/hammer.prefix'
'src/defines.js'
'src/hammer.js'
'src/*.js'
'src/**/*.js'
'src/instance.js'
'src/export.js'
'src/hammer.suffix']
dest: 'hammer.js'
Expand Down
10 changes: 0 additions & 10 deletions src/defines.js

This file was deleted.

33 changes: 33 additions & 0 deletions src/hammer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
var HAMMER_OPTIONS = {
touchAction: 'pan-y'
};

/**
* hammer instance for an element
* @param element
* @param options
* @constructor
*/
function Hammer(element, options) {
this.element = element;
this.options = options || HAMMER_OPTIONS;

this.sessions = [];

this.input = new Input(this);
this.touchAction = new TouchAction(this, this.options.touchAction);
}

Hammer.defaults = HAMMER_OPTIONS;

/**
* destroy the instance
*/
Hammer.prototype.destroy = function() {
this.sessions.length = 0;
this.input.destroy();
};




120 changes: 108 additions & 12 deletions src/input.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,22 @@
var MOBILE_REGEX = /mobile|tablet|ip(ad|hone|od)|android|silk/i;

var SUPPORT_POINTEREVENT = window.PointerEvent || window.msPointerEvent;
var SUPPORT_TOUCH = ("ontouchstart" in window);
var SUPPORT_ONLY_TOUCH = SUPPORT_TOUCH && MOBILE_REGEX.test(navigator.userAgent);

var INPUT_TYPE_TOUCH = 'touch';
var INPUT_TYPE_MOUSE = 'mouse';

var INPUT_EVENT_START = 'start';
var INPUT_EVENT_MOVE = 'move';
var INPUT_EVENT_END = 'end';

var DIRECTION_LEFT = 'left';
var DIRECTION_RIGHT = 'right';
var DIRECTION_UP = 'up';
var DIRECTION_DOWN = 'down';
var DIRECTION_NONE = 'none';

/**
* create new input type instance
* @param inst
Expand All @@ -6,24 +25,26 @@
*/
function Input(inst) {
var type = 'TouchMouse';
if(SUPPORT_POINTEREVENTS) {
type = 'PointerEvents';
} else if(SUPPORT_ONLY_TOUCHEVENTS) {
if(SUPPORT_POINTEREVENT) {
type = 'PointerEvent';
} else if(SUPPORT_ONLY_TOUCH) {
type = 'Touch';
} else if(!SUPPORT_TOUCH) {
type = 'Mouse';
}
return new Input[type](inst, inputHandler);
}

/**
* handle input events
* @param inst
* @param inputType
* @param inputEventType
* @param inputData
*/
function inputHandler(inst, inputType, inputData) {
function inputHandler(inst, inputEventType, inputData) {
var session;

if(inputType == 'start') {
if(inputEventType == INPUT_EVENT_START) {
// create session
session = new Session(inst);
inst.sessions.unshift(session);
Expand All @@ -32,23 +53,98 @@ function inputHandler(inst, inputType, inputData) {
session = inst.sessions[0];
}

extendInputData(inputType, inputData);
computeInputData(session, inputEventType, inputData);

// update the session and run gestures
session.update(inputData);
}

/**
* extend the data with some usable properties like scale, rotate, velocity etc
* @param inputType
* @param session
* @param inputEventType
* @param inputData
* @returns inputData
*/
function extendInputData(inputType, inputData) {
inputData.inputType = inputType;
function computeInputData(session, inputEventType, inputData) {
var event = inputData._event;

if(!session.firstInput) {
session.firstInput = {
timeStamp: event.timeStamp,
pointers: inputData.pointers,
center: getCenter(inputData.pointers)
};
}

inputData.inputEventType = inputEventType;

inputData.center = getCenter(inputData.pointers);
inputData.direction = getDirection(inputData.center, session.firstInput.center);
inputData.distance = getDistance(inputData.center, session.firstInput.center);

inputData.scale = 1;
inputData.rotation = 0;
}

/**
* get the center of all the pointers
* @method getCenter
* @param {Array} pointers
* @return {Object} center contains `x` and `y` properties
*/
function getCenter(pointers) {
// no need to loop when only one touch
if(pointers.length === 1) {
return {
x: pointers[0].clientX,
y: pointers[0].clientY
};
}

return inputData;
var x = [],
y = [];

each(pointers, function(pointer) {
x.push(pointer.clientX);
y.push(pointer.clientY);
});

return {
x: (Math.min.apply(Math, x) + Math.max.apply(Math, x)) / 2,
y: (Math.min.apply(Math, y) + Math.max.apply(Math, y)) / 2
};
}

/**
* do a small comparision to get the direction between two center pointers
* @method getDirection
* @param {Object} center1
* @param {Object} center2
* @return {String} direction matches `DIRECTION_LEFT|RIGHT|UP|DOWN`
*/
function getDirection(center1, center2) {
var x = center1.x - center2.x,
y = center1.y - center2.y;

if(x == y) {
return DIRECTION_NONE;
}

if(Math.abs(x) >= Math.abs(y)) {
return x > 0 ? DIRECTION_LEFT : DIRECTION_RIGHT;
}
return y > 0 ? DIRECTION_UP : DIRECTION_DOWN;
}

/**
* calculate the distance between two center pointers
* @method getDistance
* @param {Object} center1
* @param {Object} center2
* @return {Number} distance
*/
function getDistance(center1, center2) {
var x = center2.x - center1.x,
y = center2.y - center1.y;
return Math.sqrt((x * x) + (y * y));
}
46 changes: 27 additions & 19 deletions src/input/mouse.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,14 @@
// constants
var INPUT_MOUSE_TYPE_MAP = {
'mousedown': INPUT_EVENT_START,
'mousemove': INPUT_EVENT_MOVE,
'mouseup': INPUT_EVENT_END,
'mouseout': INPUT_EVENT_END
};

var INPUT_MOUSE_EVENTS = 'mousedown mousemove mouseup';
var INPUT_MOUSE_WINDOW_EVENTS = 'mouseout';

/**
* Mouse events input
* @param inst
Expand All @@ -8,12 +19,13 @@ Input.Mouse = function(inst, callback) {
this.inst = inst;
this.callback = callback;

this._allow = true; // used by Input.TouchMouse to disable mouse events
this._pressed = false; // mousedown state

this._handler = bindFn(this.handler, this);
this._events = 'mousedown mousemove mouseup';
addEvent(this.inst.element, this._events, this._handler);
addEvent(window, 'mouseout', this._handler);

this._pressed = false;
addEvent(this.inst.element, INPUT_MOUSE_EVENTS, this._handler);
addEvent(window, INPUT_MOUSE_WINDOW_EVENTS, this._handler);
};

Input.Mouse.prototype = {
Expand All @@ -26,37 +38,33 @@ Input.Mouse.prototype = {
this._pressed = true;
}

// mousebutton must be down
if(!this._pressed) {
// mousebutton must be down, and mouse events are allowed (because of the TouchMouse input)
if(!this._pressed || !this._allow) {
return;
}

if(ev.type == 'mouseup' || ev.type == 'mouseout') {
this._pressed = false;
}

// fake identifier
ev.identifier = 1;

var data = {
pointers: ev,
changedPointers: ev,
pointerType: 'mouse',
pointers: [ev],
changedPointers: [ev],
pointerType: INPUT_TYPE_MOUSE,
_event: ev
};

var types = {
'mousedown': 'start',
'mousemove': 'move',
'mouseup': 'end',
'mouseout': 'end'
};

this.callback(this.inst, types[ev.type], data);
this.callback(this.inst, INPUT_MOUSE_TYPE_MAP[ev.type], data);
},

/**
* remove the event listeners
*/
destroy: function() {
removeEvent(this.inst.element, this._events, this._handler);
removeEvent(window, 'mouseout', this._handler);
removeEvent(this.inst.element, INPUT_MOUSE_EVENTS, this._handler);
removeEvent(window, INPUT_MOUSE_WINDOW_EVENTS, this._handler);
}
};
3 changes: 3 additions & 0 deletions src/input/pointerevent.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Input.PointerEvent = function(pointers) {

};
3 changes: 0 additions & 3 deletions src/input/pointerevents.js

This file was deleted.

36 changes: 23 additions & 13 deletions src/input/touch.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
var INPUT_TOUCH_TYPE_MAP = {
'touchstart': INPUT_EVENT_START,
'touchmove': INPUT_EVENT_MOVE,
'touchend': INPUT_EVENT_END,
'touchcancel': INPUT_EVENT_END
};

var INPUT_TOUCH_EVENTS = 'touchstart touchmove touchend touchcancel';

/**
* Touch events input
* @param inst
Expand All @@ -9,9 +18,7 @@ Input.Touch = function(inst, callback) {
this.callback = callback;

this._handler = bindFn(this.handler, this);
this._events = 'touchstart touchmove touchend touchcancel';

addEvent(this.inst.element, this._events, this._handler);
addEvent(this.inst.element, INPUT_TOUCH_EVENTS, this._handler);
};

Input.Touch.prototype = {
Expand All @@ -22,33 +29,36 @@ Input.Touch.prototype = {
handler: function(ev) {
var touches = this.normalizeTouches(ev);
var data = {
pointers: touches.all,
changedPointers: touches.changed,
pointerType: 'touch',
pointers: touches[0],
changedPointers: touches[1],
pointerType: INPUT_TYPE_TOUCH,
_event: ev
};

this.callback(this.inst, ev.type.replace('touch',''), data);
this.callback(this.inst, INPUT_TOUCH_TYPE_MAP[ev.type], data);
},

/**
* make sure all browsers return the same touches
* @param ev
* @returns {{all: *, changed: *}}
* @returns [all, changed]
*/
normalizeTouches: function(ev) {
return {
var changedTouches = toArray(ev.changedTouches);
var touches = toArray(ev.touches).concat(changedTouches);

return [
// should contain all the touches, touches + changedTouches
all: ev.touches,
uniqueArray(touches, 'identifier'),
// should contain only the touches that have changed
changed: ev.changedTouches
};
changedTouches
];
},

/**
* remove the event listeners
*/
destroy: function() {
removeEvent(this.inst.element, this._events, this._handler);
removeEvent(this.inst.element, INPUT_TOUCH_EVENTS, this._handler);
}
};
Loading

0 comments on commit 712f5f6

Please sign in to comment.