Skip to content

Commit

Permalink
support touch events
Browse files Browse the repository at this point in the history
  • Loading branch information
hankhsiao committed Mar 4, 2016
1 parent 0c8f245 commit 5869b59
Show file tree
Hide file tree
Showing 6 changed files with 309 additions and 134 deletions.
10 changes: 10 additions & 0 deletions README.md
Expand Up @@ -78,6 +78,14 @@ The format of the payload is:
resize: {
width: <Number>, // The client width
height: <Number> // The client height
},
// you need to pass options.enableTouchInfo = true to subscribe to get the following data
touch: {
axisIntention: <String>, // 'x', 'y', or ''.
startX: <Number>,
startY: <Number>,
deltaX: <Number>,
deltaY: <Number>
}
}
```
Expand All @@ -94,6 +102,8 @@ The format of the payload is:
`options.enableResizeInfo = true` allows of getting `width` and `height` of client.
`options.enableTouchInfo = true` allows of getting touch information (see above).
`eventType` could be one of the following:
1. scroll - window.scoll
Expand Down
70 changes: 63 additions & 7 deletions src/AugmentedEvent.js
Expand Up @@ -13,13 +13,22 @@ var scroll = {
delta: 0,
top: 0
};
var touch = {
axisIntention: '',
startX: 0,
startY: 0,
deltaX: 0,
deltaY: 0
};

// global variables
var doc;
var docBody;
var docEl;
var win;

var INTENTION_THRESHOLD = 5;

if (typeof window !== 'undefined') {
win = window;
doc = win.document || document;
Expand All @@ -34,19 +43,38 @@ if (typeof window !== 'undefined') {
*/
function ArgmentedEvent(option) {
option = option || {};
this.type = option.type || '';
var mainType = (option.mainType || '').toLowerCase();
var subType = (option.subType || '').toLowerCase();

this.mainType = mainType;
this.subType = subType;
this.type = mainType + subType.charAt(0).toUpperCase() + subType.slice(1) || '';
this.scroll = scroll;
this.resize = resize;
this.touch = touch;
}

ArgmentedEvent.prototype = {
update: function update (mainType) {
var top;
getXY: function (touch) {
var t = { x: 0, y: 0};

if (globalVars.enableScrollInfo &&
(mainType === 'scroll' || mainType === 'touchmove')
) {
top = docEl.scrollTop + docBody.scrollTop;
if (touch.pageX || touch.pageY) {
t.x = touch.pageX;
t.y = touch.pageY;
} else {
t.x = touch.clientX + docBody.scrollLeft + docEl.scrollLeft;
t.y = touch.clientY + docBody.scrollTop + docEl.scrollTop;
}

return t;
},

update: function update(e) {
var mainType = this.mainType;
var subType = this.subType;

if (globalVars.enableScrollInfo && (mainType === 'scroll' || mainType === 'touchmove')) {
var top = docEl.scrollTop + docBody.scrollTop;
// Prevent delta from being 0
if (top !== this.scroll.top) {
this.scroll.delta = top - this.scroll.top;
Expand All @@ -57,6 +85,34 @@ ArgmentedEvent.prototype = {
this.resize.width = win.innerWidth || docEl.clientWidth;
this.resize.height = win.innerHeight || docEl.clientHeight;
}
if (globalVars.enableTouchInfo && e.touches &&
(mainType === 'touchstart' || mainType === 'touchmove' || mainType === 'touchend')
) {
var pos;
var absX;
var absY;
if (mainType === 'touchstart' || subType === 'start') {
pos = this.getXY(e.touches[0]);
this.touch.axisIntention = '';
this.touch.startX = pos.x;
this.touch.startY = pos.y;
this.touch.deltaX = 0;
this.touch.deltaY = 0;
} else if (mainType === 'touchmove') {
pos = this.getXY(e.touches[0]);
this.touch.deltaX = pos.x - this.touch.startX;
this.touch.deltaY = pos.y - this.touch.startY;
if (this.touch.axisIntention === '') {
absX = Math.abs(this.touch.deltaX);
absY = Math.abs(this.touch.deltaY);
if (absX > INTENTION_THRESHOLD && absX >= absY) {
this.touch.axisIntention = 'x';
} else if (absY > INTENTION_THRESHOLD && absY > absX) {
this.touch.axisIntention = 'y';
}
}
}
}
}
};

Expand Down
50 changes: 26 additions & 24 deletions src/mainEventConnectors.js
Expand Up @@ -2,7 +2,7 @@
* Copyright 2015, Yahoo! Inc.
* Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms.
*/
/* global window, document, setTimeout */
/* global window, document, setTimeout */
'use strict';

var _clone = require('lodash/lang/clone');
Expand All @@ -24,10 +24,12 @@ var EVENT_END_DELAY = require('./constants').EVENT_END_DELAY;
// global variables
var doc;
var win;
var body;

if (typeof window !== 'undefined') {
win = window;
doc = win.document || document;
body = doc.body;
}

/**
Expand All @@ -41,15 +43,15 @@ if (typeof window !== 'undefined') {
* @param {String} throttledMainEvent - A throttled main event
* @return {Object} An event remover
*/
function connectThrottle (throttledEvent, cb, ctx, throttledMainEvent) {
function connectThrottle(throttledEvent, cb, ctx, throttledMainEvent) {
EE.on(throttledEvent, cb, ctx);
throttledMainEvent = throttledMainEvent || throttledEvent;
connections[throttledMainEvent] = (connections[throttledMainEvent] || 0) + 1;
return {
_type: throttledEvent,
_cb: cb,
_ctx: ctx,
unsubscribe: function unsubscribe () {
unsubscribe: function unsubscribe() {
if (!this._type) {
return;
}
Expand Down Expand Up @@ -84,8 +86,8 @@ function connectThrottle (throttledEvent, cb, ctx, throttledMainEvent) {
* @param {String} mainEvent - A browser event, like scroll or resize.
* @param {String} event - A subscribe event.
*/
function connectContinuousEvent (target, mainEvent, event) {
return function throttleEvent (throttleRate, cb, context) {
function connectContinuousEvent(target, mainEvent, event) {
return function throttleEvent(throttleRate, cb, context) {
var throttledStartEvent = mainEvent + 'Start:' + throttleRate;
var throttledEndEvent = mainEvent + 'End:' + throttleRate;
var throttledMainEvent = mainEvent + ':' + throttleRate;
Expand All @@ -99,12 +101,12 @@ function connectContinuousEvent (target, mainEvent, event) {
}

var ae = {
start: new AugmentedEvent({type: mainEvent + 'Start'}), // start
main: new AugmentedEvent({type: mainEvent}), // main
end: new AugmentedEvent({type: mainEvent + 'End'}), // end
};
start: new AugmentedEvent({ mainType: mainEvent, subType: 'start' }), // start
main: new AugmentedEvent({ mainType: mainEvent }), // main
end: new AugmentedEvent({ mainType: mainEvent, subType: 'end' }) };

// No throttle for throttleRate = 0
// end
if (throttleRate === 'raf') {
throttleRate = 16; // Set as a number for setTimeout later.
handler = rAFThrottle(handler);
Expand All @@ -113,19 +115,19 @@ function connectContinuousEvent (target, mainEvent, event) {
}

var timer;
function endCallback (e) {
ae.end.update(mainEvent);
function endCallback(e) {
ae.end.update(e);
EE.emit(throttledEndEvent, e, ae.end);
timer = null;
}
function handler (e) {
ae.start.update(mainEvent);
function handler(e) {
if (!timer) {
ae.start.update(e);
EE.emit(throttledStartEvent, e, ae.start);
}
clearTimeout(timer);

// No need to call ae.main.update(), because ae.start.update is called, everything is update-to-date.
ae.main.update(e);
EE.emit(throttledMainEvent, e, ae.main);
if (!leIE8) {
timer = setTimeout(endCallback.bind(null, e), throttleRate + EVENT_END_DELAY);
Expand All @@ -143,8 +145,8 @@ function connectContinuousEvent (target, mainEvent, event) {
};
}

function connectDiscreteEvent (target, event) {
return function throttleEvent (throttleRate, cb, context) {
function connectDiscreteEvent(target, event) {
return function throttleEvent(throttleRate, cb, context) {
// no throttling for discrete event
var throttledEvent = event + ':0';

Expand All @@ -155,10 +157,10 @@ function connectDiscreteEvent (target, event) {
return remover;
}

var ae = new AugmentedEvent({type: event});
var ae = new AugmentedEvent({ mainType: event });

function handler (e) {
ae.update(event);
function handler(e) {
ae.update(e);
EE.emit(throttledEvent, e, ae);
}

Expand All @@ -175,9 +177,9 @@ module.exports = {
resizeEnd: connectContinuousEvent(win, 'resize', 'resizeEnd'),
resize: connectContinuousEvent(win, 'resize', 'resize'),
visibilitychange: connectDiscreteEvent(doc, 'visibilitychange'),
touchmoveStart: connectContinuousEvent(win, 'touchmove', 'touchmoveStart'),
touchmoveEnd: connectContinuousEvent(win, 'touchmove', 'touchmoveEnd'),
touchmove: connectContinuousEvent(win, 'touchmove', 'touchmove'),
touchstart: connectDiscreteEvent(doc, 'touchstart'),
touchend: connectDiscreteEvent(doc, 'touchend'),
touchmoveStart: connectContinuousEvent(body, 'touchmove', 'touchmoveStart'),
touchmoveEnd: connectContinuousEvent(body, 'touchmove', 'touchmoveEnd'),
touchmove: connectContinuousEvent(body, 'touchmove', 'touchmove'),
touchstart: connectDiscreteEvent(body, 'touchstart'),
touchend: connectDiscreteEvent(body, 'touchend')
};
1 change: 1 addition & 0 deletions src/subscribe.js
Expand Up @@ -44,6 +44,7 @@ function subscribe(type, cb, options) {
// once those variables enabled, then never disabled.
globalVars.enableScrollInfo = globalVars.enableScrollInfo || options.enableScrollInfo || false;
globalVars.enableResizeInfo = globalVars.enableResizeInfo || options.enableResizeInfo || false;
globalVars.enableTouchInfo = globalVars.enableTouchInfo || options.enableTouchInfo || false;

return mainEventConnectors[type](throttleRate, cb, options.context);
}
Expand Down
10 changes: 8 additions & 2 deletions tests/lib/setup.js
Expand Up @@ -41,10 +41,16 @@ window = {
};
document = {
documentElement: {
scrollTop: 10
scrollTop: 10,
scrollLeft: 0
},
body: {
scrollTop: 0
scrollTop: 0,
scrollLeft: 0,
addEventListener: addEventListener,
removeEventListener: removeEventListener,
attachEvent: addEventListener,
detachEvent: removeEventListener
},
addEventListener: addEventListener,
removeEventListener: removeEventListener,
Expand Down

0 comments on commit 5869b59

Please sign in to comment.