diff options
Diffstat (limited to 'js/hammer.js')
-rwxr-xr-x | js/hammer.js | 586 |
1 files changed, 586 insertions, 0 deletions
diff --git a/js/hammer.js b/js/hammer.js new file mode 100755 index 0000000..44a5802 --- /dev/null +++ b/js/hammer.js | |||
@@ -0,0 +1,586 @@ | |||
1 | /* | ||
2 | * Hammer.JS | ||
3 | * version 0.4 | ||
4 | * author: Eight Media | ||
5 | * https://github.com/EightMedia/hammer.js | ||
6 | */ | ||
7 | function Hammer(element, options, undefined) | ||
8 | { | ||
9 | var self = this; | ||
10 | |||
11 | var defaults = { | ||
12 | // prevent the default event or not... might be buggy when false | ||
13 | prevent_default : false, | ||
14 | css_hacks : true, | ||
15 | |||
16 | drag : true, | ||
17 | drag_vertical : true, | ||
18 | drag_horizontal : true, | ||
19 | // minimum distance before the drag event starts | ||
20 | drag_min_distance : 20, // pixels | ||
21 | |||
22 | // pinch zoom and rotation | ||
23 | transform : true, | ||
24 | scale_treshold : 0.1, | ||
25 | rotation_treshold : 15, // degrees | ||
26 | |||
27 | tap : true, | ||
28 | tap_double : true, | ||
29 | tap_max_interval : 300, | ||
30 | tap_double_distance: 20, | ||
31 | |||
32 | hold : true, | ||
33 | hold_timeout : 500 | ||
34 | }; | ||
35 | options = mergeObject(defaults, options); | ||
36 | |||
37 | // some css hacks | ||
38 | (function() { | ||
39 | if(!options.css_hacks) { | ||
40 | return false; | ||
41 | } | ||
42 | |||
43 | var vendors = ['webkit','moz','ms','o','']; | ||
44 | var css_props = { | ||
45 | "userSelect": "none", | ||
46 | "touchCallout": "none", | ||
47 | "userDrag": "none", | ||
48 | "tapHighlightColor": "rgba(0,0,0,0)" | ||
49 | }; | ||
50 | |||
51 | var prop = ''; | ||
52 | for(var i = 0; i < vendors.length; i++) { | ||
53 | for(var p in css_props) { | ||
54 | prop = p; | ||
55 | if(vendors[i]) { | ||
56 | prop = vendors[i] + prop.substring(0, 1).toUpperCase() + prop.substring(1); | ||
57 | } | ||
58 | element.style[ prop ] = css_props[p]; | ||
59 | } | ||
60 | } | ||
61 | })(); | ||
62 | |||
63 | // holds the distance that has been moved | ||
64 | var _distance = 0; | ||
65 | |||
66 | // holds the exact angle that has been moved | ||
67 | var _angle = 0; | ||
68 | |||
69 | // holds the diraction that has been moved | ||
70 | var _direction = 0; | ||
71 | |||
72 | // holds position movement for sliding | ||
73 | var _pos = { }; | ||
74 | |||
75 | // how many fingers are on the screen | ||
76 | var _fingers = 0; | ||
77 | |||
78 | var _first = false; | ||
79 | |||
80 | var _gesture = null; | ||
81 | var _prev_gesture = null; | ||
82 | |||
83 | var _touch_start_time = null; | ||
84 | var _prev_tap_pos = {x: 0, y: 0}; | ||
85 | var _prev_tap_end_time = null; | ||
86 | |||
87 | var _hold_timer = null; | ||
88 | |||
89 | var _offset = {}; | ||
90 | |||
91 | // keep track of the mouse status | ||
92 | var _mousedown = false; | ||
93 | |||
94 | var _event_start; | ||
95 | var _event_move; | ||
96 | var _event_end; | ||
97 | |||
98 | |||
99 | /** | ||
100 | * angle to direction define | ||
101 | * @param float angle | ||
102 | * @return string direction | ||
103 | */ | ||
104 | this.getDirectionFromAngle = function( angle ) | ||
105 | { | ||
106 | var directions = { | ||
107 | down: angle >= 45 && angle < 135, //90 | ||
108 | left: angle >= 135 || angle <= -135, //180 | ||
109 | up: angle < -45 && angle > -135, //270 | ||
110 | right: angle >= -45 && angle <= 45 //0 | ||
111 | }; | ||
112 | |||
113 | var direction, key; | ||
114 | for(key in directions){ | ||
115 | if(directions[key]){ | ||
116 | direction = key; | ||
117 | break; | ||
118 | } | ||
119 | } | ||
120 | return direction; | ||
121 | }; | ||
122 | |||
123 | |||
124 | /** | ||
125 | * count the number of fingers in the event | ||
126 | * when no fingers are detected, one finger is returned (mouse pointer) | ||
127 | * @param event | ||
128 | * @return int fingers | ||
129 | */ | ||
130 | function countFingers( event ) | ||
131 | { | ||
132 | // there is a bug on android (until v4?) that touches is always 1, | ||
133 | // so no multitouch is supported, e.g. no, zoom and rotation... | ||
134 | return event.touches ? event.touches.length : 1; | ||
135 | } | ||
136 | |||
137 | |||
138 | /** | ||
139 | * get the x and y positions from the event object | ||
140 | * @param event | ||
141 | * @return array [{ x: int, y: int }] | ||
142 | */ | ||
143 | function getXYfromEvent( event ) | ||
144 | { | ||
145 | event = event || window.event; | ||
146 | |||
147 | // no touches, use the event pageX and pageY | ||
148 | if(!event.touches) { | ||
149 | var doc = document, | ||
150 | body = doc.body; | ||
151 | |||
152 | return [{ | ||
153 | x: event.pageX || event.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && doc.clientLeft || 0 ), | ||
154 | y: event.pageY || event.clientY + ( doc && doc.scrollTop || body && body.scrollTop || 0 ) - ( doc && doc.clientTop || body && doc.clientTop || 0 ) | ||
155 | }]; | ||
156 | } | ||
157 | // multitouch, return array with positions | ||
158 | else { | ||
159 | var pos = [], src; | ||
160 | for(var t=0, len=event.touches.length; t<len; t++) { | ||
161 | src = event.touches[t]; | ||
162 | pos.push({ x: src.pageX, y: src.pageY }); | ||
163 | } | ||
164 | return pos; | ||
165 | } | ||
166 | } | ||
167 | |||
168 | |||
169 | /** | ||
170 | * calculate the angle between two points | ||
171 | * @param object pos1 { x: int, y: int } | ||
172 | * @param object pos2 { x: int, y: int } | ||
173 | */ | ||
174 | function getAngle( pos1, pos2 ) | ||
175 | { | ||
176 | return Math.atan2(pos2.y - pos1.y, pos2.x - pos1.x) * 180 / Math.PI; | ||
177 | } | ||
178 | |||
179 | /** | ||
180 | * trigger an event/callback by name with params | ||
181 | * @param string name | ||
182 | * @param array params | ||
183 | */ | ||
184 | function triggerEvent( eventName, params ) | ||
185 | { | ||
186 | // return touches object | ||
187 | params.touches = getXYfromEvent(params.originalEvent); | ||
188 | params.type = eventName; | ||
189 | |||
190 | // trigger callback | ||
191 | if(isFunction(self["on"+ eventName])) { | ||
192 | self["on"+ eventName].call(self, params); | ||
193 | } | ||
194 | } | ||
195 | |||
196 | |||
197 | /** | ||
198 | * cancel event | ||
199 | * @param object event | ||
200 | * @return void | ||
201 | */ | ||
202 | |||
203 | function cancelEvent(event){ | ||
204 | event = event || window.event; | ||
205 | if(event.preventDefault){ | ||
206 | event.preventDefault(); | ||
207 | }else{ | ||
208 | event.returnValue = false; | ||
209 | event.cancelBubble = true; | ||
210 | } | ||
211 | } | ||
212 | |||
213 | |||
214 | /** | ||
215 | * reset the internal vars to the start values | ||
216 | */ | ||
217 | function reset() | ||
218 | { | ||
219 | _pos = {}; | ||
220 | _first = false; | ||
221 | _fingers = 0; | ||
222 | _distance = 0; | ||
223 | _angle = 0; | ||
224 | _gesture = null; | ||
225 | } | ||
226 | |||
227 | |||
228 | var gestures = { | ||
229 | // hold gesture | ||
230 | // fired on touchstart | ||
231 | hold : function(event) | ||
232 | { | ||
233 | // only when one finger is on the screen | ||
234 | if(options.hold) { | ||
235 | _gesture = 'hold'; | ||
236 | clearTimeout(_hold_timer); | ||
237 | |||
238 | _hold_timer = setTimeout(function() { | ||
239 | if(_gesture == 'hold') { | ||
240 | triggerEvent("hold", { | ||
241 | originalEvent : event, | ||
242 | position : _pos.start | ||
243 | }); | ||
244 | } | ||
245 | }, options.hold_timeout); | ||
246 | } | ||
247 | }, | ||
248 | |||
249 | |||
250 | // drag gesture | ||
251 | // fired on mousemove | ||
252 | drag : function(event) | ||
253 | { | ||
254 | // get the distance we moved | ||
255 | var _distance_x = _pos.move[0].x - _pos.start[0].x; | ||