OSDN Git Service

f8b95358694d100707a259931cd0bd3137ddcc3b
[pettanr/clientJs.git] / 0.6.x / js / 20_ui / 05_XUI_Gesture.js
1 var XUI_GestureUtils = {\r
2                 /**\r
3                  * get the center of all the touches\r
4                  * @param   {Array}     touches\r
5                  * @returns {Object}    center\r
6                  */\r
7                 getCenter : function( touches ){\r
8                         var i = 0,\r
9                                 l = touches.length,\r
10                                 x, y, minX, minY, maxX, maxY;\r
11 \r
12                         switch( l ){\r
13                                 case 0 :\r
14                                         return {};\r
15                                 case 1 :\r
16                                         return {\r
17                                                 pageX : touches[ 0 ].pageX,\r
18                                                 pageY : touches[ 0 ].pageY\r
19                                         };\r
20                                 case 2 :\r
21                                         return {\r
22                                                 pageX : ( touches[ 0 ].pageX + touches[ 1 ].pageX ) / 2,\r
23                                                 pageY : ( touches[ 0 ].pageY + touches[ 1 ].pageY ) / 2\r
24                                         };\r
25                         };\r
26                         minX = minY = 1 / 0;\r
27                         maxX = maxY = - 1 / 0;\r
28                         for( ; i < l; ++i ){\r
29                                 x    = touches[ i ].pageX;\r
30                                 minX = x < minX ? x : minX;\r
31                                 maxX = maxX < x ? x : maxX;\r
32                                 y    = touches[ i ].pageY;\r
33                                 minY = y < minY ? y : minY;\r
34                                 maxY = maxY < y ? y : maxY;\r
35                         };\r
36                         return {\r
37                                 pageX : ( minX + maxX ) / 2 | 0,\r
38                                 pageY : ( minY + maxY ) / 2 | 0\r
39                         };\r
40                 },\r
41 \r
42                 /**\r
43                  * calculate the velocity between two points\r
44                  * @param   {Number}    deltaTime\r
45                  * @param   {Number}    deltaX\r
46                  * @param   {Number}    deltaY\r
47                  * @returns {Object}    velocity\r
48                  */\r
49                 getVelocity : function( deltaTime, deltaX, deltaY ) {\r
50                         return {\r
51                                 x : Math.abs( deltaX / deltaTime ) || 0,\r
52                                 y : Math.abs( deltaY / deltaTime ) || 0\r
53                         };\r
54                 },\r
55 \r
56                 /**\r
57                  * calculate the angle between two coordinates\r
58                  * @param   {Touch}     touch1\r
59                  * @param   {Touch}     touch2\r
60                  * @returns {Number}    angle\r
61                  */\r
62                 getAngle : function( touch1, touch2 ){\r
63                         var y = touch2.pageY - touch1.pageY,\r
64                                 x = touch2.pageX - touch1.pageX;\r
65                         return Math.atan2( y, x ) * 180 / Math.PI;\r
66                 },\r
67 \r
68                 /**\r
69                  * angle to direction define\r
70                  * @param   {Touch}     touch1\r
71                  * @param   {Touch}     touch2\r
72                  * @returns {String}    direction constant, like 'left'\r
73                  */\r
74                 getDirection : function( touch1, touch2 ){\r
75                         var x = touch1.pageX - touch2.pageX,\r
76                                 y = touch1.pageY - touch2.pageY;\r
77                         return Math.abs( y ) <= Math.abs( x ) ?\r
78                                 ( x > 0 ? 'left' : 'right' ) :\r
79                                 ( y > 0 ? 'up'   : 'down' );\r
80                 },\r
81 \r
82                 /**\r
83                  * calculate the distance between two touches\r
84                  * @param   {Touch}     touch1\r
85                  * @param   {Touch}     touch2\r
86                  * @returns {Number}    distance\r
87                  */\r
88                 getDistance : function( touch1, touch2 ){\r
89                         var x = touch2.pageX - touch1.pageX,\r
90                                 y = touch2.pageY - touch1.pageY;\r
91                         return Math.sqrt( ( x * x ) + ( y * y ) );\r
92                 },\r
93 \r
94                 /**\r
95                  * calculate the scale factor between two touchLists (fingers)\r
96                  * no scale is 1, and goes down to 0 when pinched together, and bigger when pinched out\r
97                  * @param   {Array}     start\r
98                  * @param   {Array}     end\r
99                  * @returns {Number}    scale\r
100                  */\r
101                 getScale : function( start, end ){\r
102                         // need two fingers...\r
103                         return ( 2 <= start.length && 2 <= end.length ) ?\r
104                                 XUI_GestureUtils.getDistance( end[ 0 ], end[ 1 ] ) / XUI_GestureUtils.getDistance( start[ 0 ], start[ 1 ] ) :\r
105                                 1;\r
106                 },\r
107 \r
108                 /**\r
109                  * calculate the rotation degrees between two touchLists (fingers)\r
110                  * @param   {Array}     start\r
111                  * @param   {Array}     end\r
112                  * @returns {Number}    rotation\r
113                  */\r
114                 getRotation : function getRotation( start, end ){\r
115                         // need two fingers\r
116                         return ( 2 <= start.length && 2 <= end.length ) ?\r
117                                 XUI_GestureUtils.getAngle( end[ 1 ], end[ 0 ] ) - XUI_GestureUtils.getAngle( start[ 1 ], start[ 0 ] ) :\r
118                                 0;\r
119                 },\r
120 \r
121                 /**\r
122                  * boolean if the direction is vertical\r
123                  * @param    {String}    direction\r
124                  * @returns  {Boolean}   is_vertical\r
125                  */\r
126                 isVertical : function isVertical( direction ){\r
127                         return direction === 'up' || direction === 'down';\r
128                 }\r
129         };\r
130 \r
131 var XUI_Gesture_POINTERS = {},\r
132         XUI_Gesture_CAPTURED = {},\r
133         XUI_Gesture_DEFAULTS = {};\r
134 \r
135 // AbstractUINode に移動\r
136 \r
137 var XUI_Gesture = Hammer = X_Class_create(\r
138         'X.UI.Gesture',\r
139         X_Class.NONE,\r
140         {\r
141                 uinodeRoot    : null,\r
142                 uinode        : null,\r
143                 options       : null,\r
144                 \r
145                 activated     : null,\r
146                 types         : null,\r
147 \r
148                 triggered     : null,\r
149                 canceled      : null,\r
150                 \r
151                 currentName   : '',\r
152                 startEvent    : null,\r
153                 lastEvent     : null,\r
154                 lastMoveEvent : null,\r
155                 \r
156                 'Constructor' : function( uinodeRoot, uinode, type, opt_options ){\r
157                         this.uinodeRoot = uinodeRoot;\r
158                         this.uinode     = uinode;\r
159                         this.options    = X_Object_override( X_Object_copy( XUI_Gesture_DEFAULTS ), opt_options );\r
160                         \r
161                         this.triggered  = {};\r
162                         this.canceled   = {};\r
163 \r
164                         uinode[ 'listen' ]( XUI_Event._POINTER_DOWN, this, XUI_Gesture_handleEvent );\r
165                         \r
166                         this[ 'listen' ]( type );\r
167                 },\r
168                 \r
169                 trigger : function( type, gesture ){\r
170                         var e;\r
171                         \r
172                         if( !this.types[ type ] ) return X_CALLBACK_NONE;\r
173                         e = X_Object_copy( gesture );\r
174                         e.type = type;\r
175                         return this.uinode[ 'dispatch' ]( e ) || X_CALLBACK_NONE;\r
176                 },\r
177                 \r
178                 listen : function( type ){\r
179                         var gestures = XUI_Gesture_LIST,\r
180                                 i = gestures.length, g;\r
181 \r
182                         for( ; i; ){\r
183                                 g = gestures[ --i ];\r
184                                 if( g.startID <= type && type <= g.endID ){\r
185                                         if( !this.activated ) this.activated = {};\r
186                                         if( !this.types ) this.types = {};\r
187                                         this.activated[ g.name ] = this.types[ type ] = 1;\r
188                                         break;\r
189                                 };\r
190                         };\r
191                 },\r
192                 \r
193                 unlisten : function( type ){\r
194                         var gestures = XUI_Gesture_LIST,\r
195                                 i = gestures.length,\r
196                                 active = this.activated, g;\r
197 \r
198                         if( !active ) return;\r
199                         for( ; i; ){\r
200                                 g = gestures[ --i ];\r
201                                 if( g.startID <= type && type <= g.endID ){\r
202                                         if( active[ g.name ] ){\r
203                                                 if( this.types[ type ] ) delete this.types[ type ];\r
204                                                 for( i = g.startID; i <= g.endID; ++i ){\r
205                                                         if( this.types[ i ] ) return;\r
206                                                 };\r
207                                                 delete active[ g.name ];\r
208                                         };\r
209                                         break;\r
210                                 };\r
211                         };\r
212                 }\r
213         }\r
214 );\r
215 \r
216 function XUI_Gesture_handleEvent( e ){\r
217                 var gestures   = XUI_Gesture_LIST,\r
218                         type       = e.type,\r
219                         uid        = e[ 'pointerId' ],\r
220                         isStart    = type === XUI_Event._POINTER_DOWN,\r
221                         isEnd      = type === XUI_Event._POINTER_UP || type === XUI_Event._POINTER_CANCEL || type === XUI_Event.POINTER_OUT,\r
222                         hammer     = this,\r
223                         isMouse    = e.pointerType === 'mouse',\r
224                         touches    = [], \r
225                         numTouches = 0,// count the total touches on the screen\r
226                         i, p, l, j, captured, ret, activated, gesture, startEv,\r
227                         deltaTime, deltaX, deltaY, velocity, center, startCenter;\r
228 \r
229                 if( !isStart && !hammer.startEvent ) return;\r
230 \r
231 if( type === XUI_Event.POINTER_OUT ) console.log( 'canceled ...' + e.button )\r
232 \r
233                 if( isEnd ){\r
234                         if( XUI_Gesture_POINTERS[ uid ] ){\r
235                                 delete XUI_Gesture_POINTERS[ uid ];\r
236                                 if( XUI_Gesture_CAPTURED[ uid ] ) delete XUI_Gesture_CAPTURED[ uid ];\r
237                         };\r
238                 } else {\r
239                         XUI_Gesture_POINTERS[ uid ] = e;\r
240                 };\r
241 \r
242                 // mousebutton must be down or a touch event\r
243                 if( ( isEnd || !isMouse || e.button === 0 ) ){\r
244                         numTouches = -1;\r
245 \r
246                         for( i in XUI_Gesture_POINTERS ){\r
247                                 if( p = XUI_Gesture_POINTERS[ i ] ){\r
248                                         // いずれかの hammer によって束縛されている場合、その束縛している hammer なら\r
249                                         captured = XUI_Gesture_CAPTURED[ p[ 'pointerId' ] ];\r
250                                         if( captured && captured !== hammer ){\r
251                                                 continue;\r
252                                         };\r
253                                         touches[ ++numTouches ] = p;\r
254                                 };\r
255                         };\r
256                         ++numTouches;\r
257 \r
258                         // if we are in a end event, but when we remove one touch and\r
259                         // we still have enough, set eventType to move\r
260                         if( !numTouches ){ // no touches, force the end event\r
261                                 isEnd = true;\r
262                         };\r
263 \r
264                         // because touchend has no touches, and we often want to use these in our gestures,\r
265                         // we send the last move event as our eventData in touchend\r
266                         ( isEnd && hammer.lastMoveEvent ) ? ( e = hammer.lastMoveEvent ) : ( hammer.lastMoveEvent = e ); // store the last move event\r
267 \r
268                         hammerEvent = X_Object_copy( e );\r
269                         hammerEvent.touches = touches;\r
270 \r
271                         if( isStart && !hammer.startEvent ){\r
272                                 console.log( '=- add -=' );\r
273                                 // already busy with a Hammer.gesture detection on an element\r
274                                 hammer.startEvent = hammerEvent;\r
275                                 hammer.uinodeRoot[ 'listen' ]( [ XUI_Event._POINTER_MOVE, XUI_Event._POINTER_UP, XUI_Event._POINTER_CANCEL, XUI_Event.POINTER_OUT ], hammer, XUI_Gesture_handleEvent );                         \r
276                         };\r
277                         \r
278                         startEv = hammer.startEvent;\r
279                         \r
280 \r
281                         // if the touches change, set the new touches over the startEvent touches\r
282                         // this because touchevents don't have all the touches on touchstart, or the\r
283                         // user must place his fingers at the EXACT same time on the screen, which is not realistic\r
284                         // but, sometimes it happens that both fingers are touching at the EXACT same time\r
285                         if( startEv && ( numTouches !== startEv.touches.length || touches !== startEv.touches ) ){\r
286                                 // extend 1 level deep to get the touchlist with the touch objects\r
287                                 startEv.touches.length = i = 0;\r
288                                 j = -1;\r
289                                 for( ; i < numTouches; ++i ){\r
290                                         startEv.touches[ ++j ] = touches[ i ];\r
291                                 };\r
292                         };\r
293 \r
294                         deltaTime   = hammerEvent.timestamp  - startEv.timestamp;\r
295                         center      = XUI_GestureUtils.getCenter( touches );\r
296                         startCenter = startEv.center;\r
297                         deltaX      = startCenter ? ( center.pageX - startCenter.pageX ) : 0;\r
298                         deltaY      = startCenter ? ( center.pageY - startCenter.pageY ) : 0;\r
299                         velocity    = XUI_GestureUtils.getVelocity( deltaTime, deltaX, deltaY );\r
300 \r
301                         X_Object_override( hammerEvent, {\r
302                                 type       : isEnd ? XUI_Event._POINTER_UP : type,\r
303                                 \r
304                                 deltaTime  : deltaTime,\r
305 \r
306                                 deltaX     : deltaX,\r
307                                 deltaY     : deltaY,\r
308 \r
309                                 velocityX  : velocity.x,\r
310                                 velocityY  : velocity.y,\r
311 \r
312                                 center     : center,\r
313                                 distance   : startCenter ? XUI_GestureUtils.getDistance( startCenter, center ) : 0,\r
314                                 angle      : startCenter ? XUI_GestureUtils.getAngle( startCenter, center ) : 0,\r
315                                 direction  : startCenter ? XUI_GestureUtils.getDirection( startCenter, center ) : 0,\r
316 \r
317                                 scale      : XUI_GestureUtils.getScale( startEv.touches, touches ),\r
318                                 rotation   : XUI_GestureUtils.getRotation( startEv.touches, touches ),\r
319 \r
320                                 startEvent : startEv\r
321                         });\r
322 \r
323                         // store as previous event event\r
324                         hammer.lastEvent = hammerEvent;\r
325                         activated = hammer.activated;\r
326                         console.log( '... ' );\r
327                         // call Hammer.gesture handlers\r
328                         for( i = 0, l = gestures.length; i < l; ++i ){\r
329                                 gesture = gestures[ i ];\r
330 \r
331                                 if( activated[ gesture.name ] && !hammer.canceled[ gesture.name ] ){\r
332                                         ( console.log( '... ' + i + ' ' + gesture.name ) );\r
333                                         // if a handler returns false, we stop with the detection\r
334                                         ( ret |= ( gesture.handler( hammerEvent, hammer ) || X_CALLBACK_NONE ) );\r
335                                 };\r
336 \r
337                                 if( ret & X_CALLBACK_CAPTURE_POINTER ){\r
338                                         for( i = touches.length; i; ){\r
339                                                 uid = touches[ --i ][ 'pointerId' ];\r
340                                                 XUI_Gesture_CAPTURED[ uid ] = hammer;\r
341                                                 //console.log( 'captured. ' + uid );\r
342                                         };\r
343                                         break;\r
344                                 } else\r
345                                 if( ret & X_CALLBACK_STOP_NOW ){\r
346                                         break;\r
347                                 };\r
348                         };\r
349                         //console.log( '----' );\r
350                 } else {\r
351                         \r
352                 };\r
353                 \r
354                 if( isEnd || ( ret & X_CALLBACK_RELEASE_POINTER ) ){\r
355                         for( i = touches.length; i; ){\r
356                                 uid = touches[ --i ][ 'pointerId' ];\r
357                                 if( XUI_Gesture_CAPTURED[ uid ] === hammer ){\r
358                                         console.log( 'released. ' + uid );\r
359                                         delete XUI_Gesture_CAPTURED[ uid ];\r
360                                 };\r
361                         };\r
362                 };\r
363 \r
364                 if( isEnd ){\r
365                         console.log( '=- clear -=' );\r
366                         hammer.uinodeRoot[ 'unlisten' ]( [ XUI_Event._POINTER_MOVE, XUI_Event._POINTER_UP, XUI_Event._POINTER_CANCEL, XUI_Event.POINTER_OUT ], hammer, XUI_Gesture_handleEvent );\r
367                         \r
368                         hammer.previous = {\r
369                                 currentName   : hammer.currentName,\r
370                                 startEvent    : hammer.startEvent,\r
371                                 lastEvent     : hammer.lastEvent,\r
372                                 lastMoveEvent : hammer.lastMoveEvent\r
373                         };\r
374                         \r
375                         X_Object_clear( hammer.triggered );\r
376                         X_Object_clear( hammer.canceled  );\r
377                         \r
378                         delete hammer.currentName;\r
379                         delete hammer.startEvent;\r
380                         delete hammer.lastEvent;\r
381                         delete hammer.lastMoveEvent;\r
382                         \r
383                         ret |= X_CALLBACK_RELEASE_POINTER;\r
384                 };\r
385                 \r
386                 return ret;\r
387 };\r
388 \r
389 \r
390 \r
391 var XUI_Gesture_LIST = [\r
392         /**\r
393          * Touch\r
394          * Called as first, tells the user has touched the screen\r
395          * @events  touch\r
396          */\r
397         {\r
398                 name     : 'touch',\r
399                 index    : -Infinity,\r
400                 defaults : {\r
401                         // call preventDefault at touchstart, and makes the element blocking by\r
402                         // disabling the scrolling of the page, but it improves gestures like\r
403                         // transforming and dragging.\r
404                         // be careful with using this, it can be very annoying for users to be stuck\r
405                         // on the page\r
406                         prevent_default : false,\r
407 \r
408                         // disable mouse events, so only touch (or pen!) input triggers events\r
409                         prevent_mouseevents : false\r
410                 },\r
411                 handler : function( e, hammer ){\r
412                         if( hammer.options.prevent_mouseevents && e[ 'pointerType' ] === 'mouse' ){\r
413                                 return X_CALLBACK_STOP_NOW;\r
414                         };\r
415 \r
416                         //hammer.options.prevent_default && e.preventDefault();\r
417 \r
418                         return e.type === XUI_Event._POINTER_DOWN && hammer.trigger( XUI_Event.TOUCH, e );\r
419                 }\r
420         },\r
421         \r
422         /**\r
423          * Transform\r
424          * User want to scale or rotate with 2 fingers\r
425          * @events  transform, transformstart, transformend, pinch, pinchin, pinchout, rotate\r
426          */\r
427         {\r
428                 name     : 'transform',\r
429                 index    : 45,\r
430                 startID  : XUI_Event.TRANSFORM,\r
431                 endID    : XUI_Event.ROTATE,\r
432                 defaults : {\r
433                         // factor, no scale is 1, zoomin is to 0 and zoomout until higher then 1\r
434                         transform_min_scale : 0.01,\r
435                         // rotation in degrees\r
436                         transform_min_rotation : 1,\r
437                         // prevent default browser behavior when two touches are on the screen\r
438                         // but it makes the element a blocking element\r
439                         // when you are using the transform gesture, it is a good practice to set this true\r
440                         transform_always_block : false\r
441                 },\r
442 \r
443                 handler : function( e, hammer ){\r
444                         var transform = this, ret = X_CALLBACK_NONE, scale_threshold, rotation_threshold;\r
445                         \r
446                         // current gesture isnt drag, but dragged is true\r
447                         // this means an other gesture is busy. now call dragend\r
448                         if( hammer.currentName !== transform.name && hammer.triggered[ transform.name ] ){\r
449                                 ret = hammer.trigger( XUI_Event.TRANSFORM_END, e );\r
450                                 delete hammer.triggered[ transform.name ];\r
451                                 return ret;\r
452                         };\r
453 \r
454                         // atleast multitouch\r
455                         if( e.touches.length < 2 ) return;\r
456 \r
457                         // prevent default when two fingers are on the screen\r
458                         //hammer.options.transform_always_block && e.preventDefault();\r
459 \r
460                         switch( e.type ){\r
461                                 case XUI_Event._POINTER_DOWN :\r
462                                         //hammer.triggered[ transform.name ] = false;\r
463                                         break;\r
464 \r
465                                 case XUI_Event._POINTER_MOVE:\r
466                                         scale_threshold    = Math.abs( 1 - e.scale );\r
467                                         rotation_threshold = Math.abs( e.rotation );\r
468 \r
469                                         // when the distance we moved is too small we skip this gesture\r
470                                         // or we can be already in dragging\r
471                                         if( scale_threshold < hammer.options.transform_min_scale && rotation_threshold < hammer.options.transform_min_rotation ) return;\r
472 \r
473                                         // we are transforming!\r
474                                         hammer.currentName = transform.name;\r
475 \r
476                                         // first time, trigger dragstart event\r
477                                         if( !hammer.triggered[ transform.name ] ){\r
478                                                 ret = hammer.trigger( XUI_Event.TRANSFORM_START, e );\r
479                                                 if( ret & X_CALLBACK_PREVENT_DEFAULT ){\r
480                                                         hammer.canceled[ transform.name ] = true;\r
481                                                         break;\r
482                                                 };\r
483                                                 hammer.triggered[ transform.name ] = true;\r
484                                                 break;\r
485                                         };\r
486 \r
487                                         ret |= hammer.trigger( XUI_Event.TRANSFORM, e );\r
488                                         // basic transform event\r
489 \r
490                                         // trigger rotate event\r
491                                         if( hammer.options.transform_min_rotation < rotation_threshold ){\r
492                                                 ret |= hammer.trigger( XUI_Event.ROTATE, e );\r
493                                         };\r
494                                         \r
495                                         // trigger pinch event\r
496                                         if( scale_threshold > hammer.options.transform_min_scale ){\r
497                                                 ret |= hammer.trigger( XUI_Event.PINCH, e );\r
498                                                 ret |= hammer.trigger( e.scale < 1 ? XUI_Event.PINCH_IN : XUI_Event.PINCH_OUT, e );\r
499                                         };\r
500                                         break;\r
501 \r
502                                 case XUI_Event.POINTER_OUT :\r
503                                 case XUI_Event._POINTER_CANCEL :\r
504                                 case XUI_Event._POINTER_UP :\r
505                                         // trigger dragend\r
506                                         ret = hammer.triggered[ transform.name ] && hammer.trigger( XUI_Event.TRANSFORM_END, e );\r
507                                         hammer.triggered[ transform.name ] = false;\r
508                                         break;\r
509                         };\r
510                         return ret;\r
511                 }\r
512         },\r
513         \r
514         /**\r
515          * Drag\r
516          * Move with x fingers (default 1) around on the page. Blocking the scrolling when\r
517          * moving left and right is a good practice. When all the drag events are blocking\r
518          * you disable scrolling on that area.\r
519          * @events  drag, dragstart, dragend, drapleft, dragright, dragup, dragdown\r
520          */\r
521         {\r
522                 name     : 'drag',\r
523                 index    : 50,\r
524                 startID  : XUI_Event.DRAG,\r
525                 endID    : XUI_Event.DRAG_DOWN,\r
526                 \r
527                 defaults : {\r
528                         drag_min_distance : 10,\r
529                         // set 0 for unlimited, but this can conflict with transform\r
530                         drag_max_touches : 1,\r
531                         // prevent default browser behavior when dragging occurs\r
532                         // be careful with it, it makes the element a blocking element\r
533                         // when you are using the drag gesture, it is a good practice to set this true\r
534                         drag_block_horizontal : false,\r
535                         drag_block_vertical : false,\r
536                         // drag_lock_to_axis keeps the drag gesture on the axis that it started on,\r
537                         // It disallows vertical directions if the initial direction was horizontal, and vice versa.\r
538                         drag_lock_to_axis : false,\r
539                         // drag lock only kicks in when distance > drag_lock_min_distance\r
540                         // This way, locking occurs only when the distance has become large enough to reliably determine the direction\r
541                         drag_lock_min_distance : 25\r
542                 },\r
543 \r
544                 handler : function( e, hammer ){\r
545                         var drag = this, last_direction, ret;\r
546 \r
547                         // current gesture isnt drag, but dragged is true\r
548                         // this means an other gesture is busy. now call dragend\r
549                         if( hammer.currentName !== drag.name && hammer.triggered[ drag.name ] ){\r
550                                 ret = hammer.trigger( XUI_Event.DRAG_END, e );\r
551                                 hammer.triggered[ drag.name ] = false;\r
552                                 return ret;\r
553                         };\r
554 \r
555                         // max touches\r
556                         if( 0 < hammer.options.drag_max_touches && hammer.options.drag_max_touches < e.touches.length ) return;\r
557                         \r
558                         switch( e.type ){\r
559                                 case XUI_Event._POINTER_DOWN :\r
560                                         hammer.triggered[ drag.name ] = false;\r
561                                         break;\r
562 \r
563                                 case XUI_Event._POINTER_MOVE :\r
564                                         // when the distance we moved is too small we skip this gesture\r
565                                         // or we can be already in dragging\r
566                                         if( e.distance < hammer.options.drag_min_distance && hammer.currentName !== drag.name ) return;\r
567 \r
568                                         // we are dragging!\r
569                                         hammer.currentName = drag.name;\r
570 \r
571                                         // lock drag to axis?\r
572                                         if( hammer.lastEvent.drag_locked_to_axis || ( hammer.options.drag_lock_to_axis && hammer.options.drag_lock_min_distance <= e.distance ) ){\r
573                                                 e.drag_locked_to_axis = true;\r
574                                         };\r
575                                         last_direction = hammer.lastEvent.direction;\r
576                                         if( e.drag_locked_to_axis && last_direction !== e.direction ){\r
577                                                 // keep direction on the axis that the drag gesture started on\r
578                                                 e.direction = XUI_GestureUtils.isVertical( last_direction ) ?\r
579                                                         ( e.deltaY < 0 ? 'up'   : 'down' ) :\r
580                                                         ( e.deltaX < 0 ? 'left' : 'right' );\r
581                                         };\r
582 \r
583                                         ret = X_CALLBACK_NONE;\r
584 \r
585                                         // first time, trigger dragstart event\r
586                                         if( !hammer.triggered[ drag.name ] ){\r
587                                                 ret = hammer.trigger( XUI_Event.DRAG_START, e );\r
588                                                 //if( ret & X_CALLBACK_PREVENT_DEFAULT ){\r
589                                                 //      hammer.canceled[ drag.name ] = true;\r
590                                                 //      break;\r
591                                                 //};\r
592                                                 ret |= X_CALLBACK_CAPTURE_POINTER;\r
593                                                 console.log( '----- drag start ....' + e.type );\r
594                                                 hammer.triggered[ drag.name ] = true;\r
595                                                 break;\r
596                                         };\r
597 \r
598                                         //console.log( '----- drag ....' + e.type );\r
599                                         // trigger normal event\r
600                                         ret = hammer.trigger( XUI_Event.DRAG, e ) | X_CALLBACK_CAPTURE_POINTER;\r
601 \r
602                                         // direction event, like dragdown\r
603                                         ret |= hammer.trigger(\r
604                                                 e.direction === 'up' ?\r
605                                                         XUI_Event.DRAG_UP :\r
606                                                 e.direction === 'down' ?\r
607                                                         XUI_Event.DRAG_DOWN :\r
608                                                 e.direction === 'left' ?\r
609                                                         XUI_Event.DRAG_LEFT :\r
610                                                         XUI_Event.DRAG_RIGHT,\r
611                                                 e\r
612                                         );\r
613 \r
614                                         // block the browser events\r
615                                         /* (\r
616                                                 ( hammer.options.drag_block_vertical   &&  XUI_GestureUtils.isVertical( e.direction ) ) ||\r
617                                                 ( hammer.options.drag_block_horizontal && !XUI_GestureUtils.isVertical( e.direction ) )\r
618                                         ) && e.preventDefault(); */\r
619                                         break;\r
620 \r
621                                 case XUI_Event.POINTER_OUT :\r
622                                         console.log( 'cancel!!' );\r
623                                 case XUI_Event._POINTER_CANCEL :\r
624                                 case XUI_Event._POINTER_UP:\r
625                                         // trigger dragend\r
626                                         if( hammer.triggered[ drag.name ] ){\r
627                                                 ret = hammer.trigger( XUI_Event.DRAG_END, e ) | X_CALLBACK_CAPTURE_POINTER;\r
628                                                 console.log( '----- drag end ....' + e.type );\r
629                                                 hammer.triggered[ drag.name ] = false;\r
630                                         };\r
631                                         break;\r
632                         };\r
633                         return ret;\r
634                 }\r
635         },\r
636 \r
637         /**\r
638          * Tap/DoubleTap\r
639          * Quick touch at a place or double at the same place\r
640          * @events  tap, doubletap\r
641          */\r
642         {\r
643                 name     : 'tap',\r
644                 index    : 100,\r
645                 startID  : XUI_Event.TAP,\r
646                 endID    : XUI_Event.DOUBLE_TAP,\r
647                 defaults : {\r
648                         tap_max_touchtime  : 250,\r
649                         tap_max_distance   : 3,\r
650                         tap_always         : true,\r
651                         doubletap_distance : 20,\r
652                         doubletap_interval : 300\r
653                 },\r
654                 handler : function( e, hammer ){\r
655                         // previous gesture, for the double tap since these are two different gesture detections\r
656                         var prev = hammer.previous;\r
657                         \r
658                         if( e.type === XUI_Event._POINTER_MOVE && hammer.options.tap_max_distance < e.distance ){\r
659                                 hammer.canceled[ 'tap' ] = true;\r
660                         };\r
661                         if( e.type === XUI_Event._POINTER_UP ){\r
662                                 // when the touchtime is higher then the max touch time\r
663                                 // or when the moving distance is too much\r
664                                 if( hammer.options.tap_max_touchtime < e.deltaTime || hammer.options.tap_max_distance < e.distance ) return;\r
665 \r
666                                 // check if double tap\r
667                                 if( prev && prev.currentName === 'tap' && ( e.timestamp - prev.lastEvent.timestamp ) < hammer.options.doubletap_interval && e.distance < hammer.options.doubletap_distance ){\r
668                                         return hammer.trigger( XUI_Event.DOUBLE_TAP, e );\r
669                                 } else\r
670                                 // do a single tap\r
671                                 if( hammer.options.tap_always ){\r
672                                         //hammer.currentName = 'tap';\r
673                                         console.log( 'tap! ' + e.deltaTime + 'ms ' + e.type );\r
674                                         return hammer.trigger( XUI_Event.TAP, e );\r
675                                 };\r
676                         };\r
677                 }\r
678         }\r
679 \r
680 ];\r
681 \r
682 (function( i, g ){\r
683         for( ; i; ){\r
684                 g = XUI_Gesture_LIST[ --i ];\r
685                 X_Object_override( XUI_Gesture_DEFAULTS, g.defaults );\r
686                 delete g.defaults;\r
687         };\r
688 })( XUI_Gesture_LIST.length );\r
689 \r