forked from madrobby/zepto
-
Notifications
You must be signed in to change notification settings - Fork 0
/
touch.js
149 lines (126 loc) · 4.71 KB
/
touch.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
// Zepto.js
// (c) 2010-2013 Thomas Fuchs
// Zepto.js may be freely distributed under the MIT license.
;(function($){
var touch = {},
touchTimeout, tapTimeout, swipeTimeout,
longTapDelay = 750, longTapTimeout,
MSPointer = 'MSPointer',
MSPointerDown = MSPointer + 'Down',
MSPointerMove = MSPointer + 'Move',
MSPointerUp = MSPointer + 'Up'
function parentIfText(node) {
return 'tagName' in node ? node : node.parentNode
}
function swipeDirection(x1, x2, y1, y2) {
var xDelta = Math.abs(x1 - x2), yDelta = Math.abs(y1 - y2)
return xDelta >= yDelta ? (x1 - x2 > 0 ? 'Left' : 'Right') : (y1 - y2 > 0 ? 'Up' : 'Down')
}
function longTap() {
longTapTimeout = null
if (touch.last) {
touch.el.trigger('longTap')
touch = {}
}
}
function cancelLongTap() {
if (longTapTimeout) clearTimeout(longTapTimeout)
longTapTimeout = null
}
function cancelAll() {
if (touchTimeout) clearTimeout(touchTimeout)
if (tapTimeout) clearTimeout(tapTimeout)
if (swipeTimeout) clearTimeout(swipeTimeout)
if (longTapTimeout) clearTimeout(longTapTimeout)
touchTimeout = tapTimeout = swipeTimeout = longTapTimeout = null
touch = {}
}
var gesture
if ('undefined' !== typeof(MSGesture)) {
gesture = new MSGesture()
gesture.target = document.body
}
function pageX(event){
return event.touches ? event.touches[0].pageX : event.pageX
}
function pageY(event){
return event.touches ? event.touches[0].pageY : event.pageY
}
function isPrimaryTouch(event){
return event.pointerType == event.MSPOINTER_TYPE_TOUCH && event.isPrimary
}
$(document).ready(function(){
var now, delta
$(document)
.bind('MSGestureEnd', function(e){
var swipe_dir = e.velocityX > 1 ? 'Right' : e.velocityX < -1 ? 'Left' : e.velocityY > 1 ? 'Down' : e.velocityY < -1 ? 'Up' : null;
if (swipe_dir) {
touch.el.trigger('swipe')
touch.el.trigger('swipe'+ swipe_dir)
}
})
.on('touchstart ' + MSPointerDown, function(e){
if(e.type == MSPointerDown && !isPrimaryTouch(e)) return;
now = Date.now()
delta = now - (touch.last || now)
touch.el = $(parentIfText(e.type == MSPointerDown ? e.target : e.touches[0].target))
touchTimeout && clearTimeout(touchTimeout)
touch.x1 = pageX(e)
touch.y1 = pageY(e)
if (delta > 0 && delta <= 250) touch.isDoubleTap = true
touch.last = now
longTapTimeout = setTimeout(longTap, longTapDelay)
// adds the current touch contact for IE gesture recognition
if (gesture && e.type == MSPointerDown) gesture.addPointer(e.pointerId);
})
.on('touchmove ' + MSPointerMove, function(e){
if(e.type == MSPointerMove && !isPrimaryTouch(e)) return;
cancelLongTap()
touch.x2 = pageX(e)
touch.y2 = pageY(e)
if (Math.abs(touch.x1 - touch.x2) > 10)
e.preventDefault()
})
.on('touchend ' + MSPointerUp, function(e){
if(e.type == MSPointerUp && !isPrimaryTouch(e)) return;
cancelLongTap()
// swipe
if ((touch.x2 && Math.abs(touch.x1 - touch.x2) > 30) ||
(touch.y2 && Math.abs(touch.y1 - touch.y2) > 30))
swipeTimeout = setTimeout(function() {
touch.el.trigger('swipe')
touch.el.trigger('swipe' + (swipeDirection(touch.x1, touch.x2, touch.y1, touch.y2)))
touch = {}
}, 0)
// normal tap
else if ('last' in touch)
// delay by one tick so we can cancel the 'tap' event if 'scroll' fires
// ('tap' fires before 'scroll')
tapTimeout = setTimeout(function() {
// trigger universal 'tap' with the option to cancelTouch()
// (cancelTouch cancels processing of single vs double taps for faster 'tap' response)
var event = $.Event('tap')
event.cancelTouch = cancelAll
touch.el.trigger(event)
// trigger double tap immediately
if (touch.isDoubleTap) {
touch.el.trigger('doubleTap')
touch = {}
}
// trigger single tap after 250ms of inactivity
else {
touchTimeout = setTimeout(function(){
touchTimeout = null
touch.el.trigger('singleTap')
touch = {}
}, 250)
}
}, 0)
})
.on('touchcancel ' + MSPointer + 'Cancel', cancelAll)
$(window).on('scroll', cancelAll)
})
;['swipe', 'swipeLeft', 'swipeRight', 'swipeUp', 'swipeDown', 'doubleTap', 'tap', 'singleTap', 'longTap'].forEach(function(m){
$.fn[m] = function(callback){ return this.on(m, callback) }
})
})(Zepto)