X-Git-Url: http://git.osdn.jp/view?a=blobdiff_plain;f=0.6.x%2Fjs%2F20_ui%2F05_XUI_Gesture.js;h=3aab9e12573cd05ae68cdb89b14be0a86ffa457e;hb=35daae003b3b017a92d0c883f120bf3baf604fba;hp=ed6bfecc68f2da33a736d2dd16ebfc627b979cfe;hpb=427c4cbb7f8b1ee674b845ade0796fcbfee0fcba;p=pettanr%2FclientJs.git diff --git a/0.6.x/js/20_ui/05_XUI_Gesture.js b/0.6.x/js/20_ui/05_XUI_Gesture.js index ed6bfec..3aab9e1 100644 --- a/0.6.x/js/20_ui/05_XUI_Gesture.js +++ b/0.6.x/js/20_ui/05_XUI_Gesture.js @@ -1,387 +1,14 @@ -/* original: - * Hammer.JS - v1.0.5 - 2013-04-07 - * http://eightmedia.github.com/hammer.js - * Jorik Tangelder , MIT license - **/ - - - var ELEENT_LIST = [], - HAMMER_LIST = [], - POINTERS = [], - ABS = new Function( 'v', 'return v<0?-v:v' ); - - function Hammer( uinodeRoot, uinode, type ){ - this.uinode = uinode; - this.enabled = true; - - Hammer.startup && Hammer.startup( uinodeRoot ); - - this.options = Hammer.defaults; - - // start detection on touchstart - Utils.addEvents( uinode, Hammer.EVENT_TYPES_START, this ); - - this[ 'listen' ]( type ); - }; - - Hammer.defaults = {}; - - Hammer.prototype.handleEvent = function( e ){ - //var sourceEventType = e.type.toLowerCase(); - - var type = IdToGestureID[ e.type ], - gestures = Detection.gestures, - numTouches = 0,// count the total touches on the screen - pointerType, i, l, touches, ret, active, gesture, startEv, - hammer, deltaTime, deltaX, deltaY, velocity, center; - - //console.log( 'Hammer@handleEvent ' + XUI_Event.IdToName[ e.type ] + ' ' + e.pointerType + ' ' + type ); - if( !type ) return; - - //console.log( e.type + ' dw:' + XUI_Event._POINTER_DOWN + ' up:' + XUI_Event._POINTER_UP + ' mv:' + XUI_Event._POINTER_MOVE ); - - if( e.pointerType ){ - type |= POINTER; - switch( e.pointerType ){ - case 'touch' : - type |= TOUCH; break; - case 'pen' : - type |= PEN; break; - case 'mouse' : - type |= MOUSE; break; - default : - return; - }; - }; - - // onmouseup, but when touchend has been fired we do nothing. - // this is for touchdevices which also fire a mouseup on touchend - if( type & MOUSE && touch_triggered ){ - return X_CALLBACK_STOP_NOW | X_CALLBACK_PREVENT_DEFAULT; - } else - // mousebutton must be down or a touch event - if( type & TOUCH || //sourceEventType.match(/touch/) || // touch events are always on screen - ( type & POINTER && type & START ) || //sourceEventType.match(/pointerdown/) || // pointerevents touch - ( type & MOUSE && e.button === 0 ) //(sourceEventType.match(/mouse/) && e.which === 1) // mouse is pressed - ){ - enable_detect = true; - }; - - //console.log( 'Hammer@handleEvent ' + IdToGestureID[ e.type ] + ' ' + e.type + ' ' + XUI_Event._POINTER_DOWN + ' ' + enable_detect ); - - // we are in a touch event, set the touch triggered bool to true, - // this for the conflicts that may occur on ios and android - //type & ( TOUCH | POINTER ) && ( touch_triggered = true ); - type & TOUCH && ( touch_triggered = true ); - //if (sourceEventType.match(/touch|pointer/)) { touch_triggered = true;} - - // when touch has been triggered in this detection session - // and we are now handling a mouse event, we stop that to prevent conflicts - if( enable_detect ){ - // update pointerevent - - POINTERS[ e.pointerId ] = type & END ? null : e; - touches = []; - numTouches = -1; - // we can use forEach since pointerEvents only is in IE10 - for( i in POINTERS ){ - POINTERS[ i ] && ( touches[ ++numTouches ] = POINTERS[ i ] ); - }; - ++numTouches; - ///console.log( 'numTouches ' + numTouches ); - - // if we are in a end event, but when we remove one touch and - // we still have enough, set eventType to move - if( 0 < numTouches && type & END ){ // eventType === Hammer.EVENT_END ){ - type = type & POINTER_TYPE_MASK | MOVE; - //eventType = Hammer.EVENT_MOVE; - } else if( !numTouches ){ - // no touches, force the end event - type = type & POINTER_TYPE_MASK | END; - //eventType = Hammer.EVENT_END; - }; - - // because touchend has no touches, and we often want to use these in our gestures, - // we send the last move event as our eventData in touchend - ( !numTouches && last_move_event !== null ) ? - ( e = last_move_event ): - ( last_move_event = e ); // store the last move event - - e = { - center : Utils.getCenter( touches ), - timeStamp : e.timeStamp, - target : e.target, - touches : touches, - eventType : type & EVENT_TYPE_MASK, - pointerType : type & POINTER_TYPE_MASK - }; - - if( type & START ){ - if( !this.enabled ) return; - // already busy with a Hammer.gesture detection on an element - if( Detection.current ) return; - Detection.current = { - hammer : this, // reference to HammerInstance we're working for - startEvent : Utils.extend( {}, e ), // start eventData for distances, timing etc - lastEvent : false, // last eventData - name : '' // current gesture we're in/detected, can be 'tap', 'hold' etc - }; - Detection.stopped = false; - hammer = this; - active = hammer.activeGesture; - } else - if( !Detection.current || Detection.stopped ){ - return; - } else { - hammer = Detection.current.hammer; - active = hammer.activeGesture; - }; - - // ---------------------------------------------------------------------------------------------------------------- - // ret = Detection.detect( e ); - - // ---------------------------------------------------------------------------------------------------------------- - // extend event data with calculations about scale, distance etc - // e = Detection.extendEventData( e ); - startEv = Detection.current.startEvent; - center = e.center; - - // if the touches change, set the new touches over the startEvent touches - // this because touchevents don't have all the touches on touchstart, or the - // user must place his fingers at the EXACT same time on the screen, which is not realistic - // but, sometimes it happens that both fingers are touching at the EXACT same time - if( startEv && ( numTouches !== startEv.touches.length || touches === startEv.touches ) ){ - // extend 1 level deep to get the touchlist with the touch objects - startEv.touches.length = i = 0; - for( ; i < numTouches; ++i ){ - startEv.touches[ startEv.touches.length ] = Utils.extend( {}, touches[ i ] ); - }; - }; - - deltaTime = e.timeStamp - startEv.timeStamp; - deltaX = center.pageX - startEv.center.pageX; - deltaY = center.pageY - startEv.center.pageY; - velocity = Utils.getVelocity( deltaTime, deltaX, deltaY ); - - Utils.extend( e, { - deltaTime : deltaTime, - - deltaX : deltaX, - deltaY : deltaY, - - velocityX : velocity.x, - velocityY : velocity.y, - - distance : Utils.getDistance( startEv.center, center ), - angle : Utils.getAngle( startEv.center, center ), - direction : Utils.getDirection( startEv.center, center ), - - scale : Utils.getScale( startEv.touches, touches ), - rotation : Utils.getRotation( startEv.touches, touches ), - - startEvent : startEv - }); - - // store as previous event event - Detection.current.lastEvent = e; - - // call Hammer.gesture handlers - for( i = 0, l = gestures.length; i < l; ++i ){ - gesture = gestures[ i ]; - if( Detection.stopped ) break; - //if( active[ gesture.name ] ) console.log( gesture.name ); - // only when the instance options have enabled this gesture - active[ gesture.name ] && - // if a handler returns false, we stop with the detection - ( ret |= ( gesture.handler( e, hammer ) || X_CALLBACK_NONE ) ); - }; - - // endevent, but not the last touch, so dont stop - type & END && numTouches === 0 && Detection.stopDetect(); - - // ---------------------------------------------------------------------------------------------------------------- - // trigger the handler - //handler.call( context, HamEvent.collectEventData( element, eventType, e ) ); - - // remove pointerevent from list - if( Hammer.HAS_POINTEREVENTS && type & END ){ // eventType === Hammer.EVENT_END ){ - numTouches = 0; - }; - }; - - //debug(sourceEventType +" "+ eventType); - - // on the end we reset everything - if( numTouches === 0 ){ - last_move_event = null; - enable_detect = false; - touch_triggered = false; - POINTERS.length = 0; - }; - - return ret; - }; - - Hammer.startup = function( uinodeRoot ){ - // find what eventtypes we add listeners to - /** - * we have different events for each device/browser - * determine what we need and set them in the Hammer.EVENT_TYPES constant - */ - // determine the eventtype we want to set - // for non pointer events browsers and mixed browsers, - // like chrome on windows8 touch laptop - var types, name; - - // Register all gestures inside Gestures - for( name in Gestures ){ - //Gestures.hasOwnProperty( name ) && - Detection.register( Gestures[ name ] ); - }; - - Hammer.EVENT_TYPES_START = [ XUI_Event._POINTER_DOWN ]; - types = [ XUI_Event._POINTER_MOVE, XUI_Event._POINTER_UP, XUI_Event._POINTER_CANCEL ]; - - // Add touch events on the document - Utils.addEvents( uinodeRoot, types, Hammer.prototype.handleEvent ); - - // Hammer is ready...! - delete Hammer.startup; - }; - - Hammer.prototype.trigger = function( type, gesture ){ - if( !this.types[ type ] ) return; - var e = Utils.extend( {}, gesture ); - e.type = type; - return this.uinode[ 'dispatch' ]( e ); - }; - - Hammer.prototype.listen = function( type ){ - var gestures = Detection.gestures, - i = gestures.length, g; - for( ; i; ){ - g = gestures[ --i ]; - if( g.startID <= type && type <= g.endID ){ - if( !this.activeGesture ) this.activeGesture = {}; - if( !this.types ) this.types = {}; - this.activeGesture[ g.name ] = this.types[ type ] = 1; - return; - }; - }; - }; - - Hammer.prototype.unlisten = function( type ){ - var gestures = Detection.gestures, - i = gestures.length, g; - if( !this.activeGesture ) return; - for( ; i; ){ - g = gestures[ --i ]; - if( g.startID <= type && type <= g.endID ){ - if( this.activeGesture[ g.name ] ){ - if( this.types[ type ] ) delete this.types[ type ]; - for( i = g.startID; i <= g.endID; ++i ){ - if( this.types[ i ] ) return; - }; - delete this.activeGesture[ g.name ]; - }; - return; - }; - }; - }; - - /* - * "Android version < 2.2" return ev.touches.length === 1 when touchend, others return ev.touches.length === 0 - */ - Hammer.DO_TOUCHES_FIX = Hammer.HAS_TOUCHEVENTS && ( X_UA[ 'Android' ] < 2.2 || X_UA[ 'Blink' ] || X_UA[ 'Opera' ] ); - - // detect touchevents - Hammer.HAS_POINTEREVENTS = true; // navigator.pointerEnabled || navigator.msPointerEnabled; - Hammer.HAS_POINTEREVENTS && console.log( 'Hammer.HAS_POINTEREVENTS : true' ); - - - // eventtypes per touchevent (start, move, end) - // are filled by HamEvent.determineEventTypes on setup - Hammer.EVENT_TYPES_START = null; - - // direction defines - Hammer.DIRECTION_DOWN = 'down'; - Hammer.DIRECTION_LEFT = 'left'; - Hammer.DIRECTION_UP = 'up'; - Hammer.DIRECTION_RIGHT = 'right'; - - // plugins namespace - Hammer.plugins = {}; - - var POINTER = 1, - TOUCH = 2, - PEN = 8, //4, - MOUSE = 8, - START = 16, - MOVE = 32, - END = 64, - CANCEL = 128, - EVENT_TYPE_MASK = START | MOVE | END, - POINTER_TYPE_MASK = POINTER | TOUCH | MOUSE | PEN, - IdToGestureID = {}; - IdToGestureID[ XUI_Event._POINTER_DOWN ] = START; - IdToGestureID[ XUI_Event._POINTER_MOVE ] = MOVE; - IdToGestureID[ XUI_Event._POINTER_UP ] = END; - IdToGestureID[ XUI_Event._POINTER_CANCEL ] = END; - - var Utils = { - - /** - * touch events with mouse fallback - * @param {HTMLElement} element - * @param {String} eventType like Hammer.EVENT_MOVE - * @param {Function} handler - */ - addEvents : function( uinode, types, context ){ - for( var i = 0; i < types.length; ++i ){ - uinode[ 'listen' ]( types[ i ], context ); - }; - }, - - /** - * extend method, - * also used for cloning when dest is an empty object - * @param {Object} dest - * @param {Object} src - * @parm {Boolean} merge do a merge - * @returns {Object} dest - */ - extend : function extend( dest, src, merge ){ - for( var key in src ){ - if( dest[ key ] !== undefined && merge ) continue; - dest[ key ] = src[ key ]; - }; - return dest; - }, - - /** - * find if a node is in the given parent - * used for event delegation tricks - * @param {HTMLElement} node - * @param {HTMLElement} parent - * @returns {boolean} has_parent - */ - hasParent : function( node, parent ){ - while( node && node.tagName ){ /* tagName for ie */ - if( node === parent ) return true; - node = node.parentNode; - }; - return false; - }, - +var XUI_GestureUtils = { /** * get the center of all the touches * @param {Array} touches * @returns {Object} center */ - getCenter : function getCenter(touches) { + getCenter : function( touches ){ var i = 0, l = touches.length, - valuesX, valuesY; + x, y, minX, minY, maxX, maxY; + switch( l ){ case 0 : return {}; @@ -396,15 +23,19 @@ pageY : ( touches[ 0 ].pageY + touches[ 1 ].pageY ) / 2 }; }; - valuesX = []; - valuesY = []; + minX = minY = 1 / 0; + maxX = maxY = - 1 / 0; for( ; i < l; ++i ){ - valuesX[ valuesX.length ] = touches[ i ].pageX; - valuesY[ valuesY.length ] = touches[ i ].pageY; + x = touches[ i ].pageX; + minX = x < minX ? x : minX; + maxX = maxX < x ? x : maxX; + y = touches[ i ].pageY; + minY = y < minY ? y : minY; + maxY = maxY < y ? y : maxY; }; return { - pageX : ( ( Math.min.apply( null, valuesX ) + Math.max.apply( null, valuesX ) ) / 2 ), - pageY : ( ( Math.min.apply( null, valuesY ) + Math.max.apply( null, valuesY ) ) / 2 ) + pageX : ( minX + maxX ) / 2 | 0, + pageY : ( minY + maxY ) / 2 | 0 }; }, @@ -415,10 +46,10 @@ * @param {Number} deltaY * @returns {Object} velocity */ - getVelocity : function getVelocity( deltaTime, deltaX, deltaY ) { + getVelocity : function( deltaTime, deltaX, deltaY ) { return { - x : ABS( deltaX / deltaTime ) || 0, - y : ABS( deltaY / deltaTime ) || 0 + x : Math.abs( deltaX / deltaTime ) || 0, + y : Math.abs( deltaY / deltaTime ) || 0 }; }, @@ -428,7 +59,7 @@ * @param {Touch} touch2 * @returns {Number} angle */ - getAngle : function getAngle(touch1, touch2) { + getAngle : function( touch1, touch2 ){ var y = touch2.pageY - touch1.pageY, x = touch2.pageX - touch1.pageX; return Math.atan2( y, x ) * 180 / Math.PI; @@ -438,14 +69,14 @@ * angle to direction define * @param {Touch} touch1 * @param {Touch} touch2 - * @returns {String} direction constant, like Hammer.DIRECTION_LEFT + * @returns {String} direction constant, like 'left' */ - getDirection : function getDirection( touch1, touch2 ){ + getDirection : function( touch1, touch2 ){ var x = touch1.pageX - touch2.pageX, y = touch1.pageY - touch2.pageY; - return ABS( y ) <= ABS( x ) ? - ( x > 0 ? Hammer.DIRECTION_LEFT : Hammer.DIRECTION_RIGHT ) : - ( y > 0 ? Hammer.DIRECTION_UP : Hammer.DIRECTION_DOWN ); + return Math.abs( y ) <= Math.abs( x ) ? + ( x > 0 ? 'left' : 'right' ) : + ( y > 0 ? 'up' : 'down' ); }, /** @@ -454,7 +85,7 @@ * @param {Touch} touch2 * @returns {Number} distance */ - getDistance : function getDistance( touch1, touch2 ){ + getDistance : function( touch1, touch2 ){ var x = touch2.pageX - touch1.pageX, y = touch2.pageY - touch1.pageY; return Math.sqrt( ( x * x ) + ( y * y ) ); @@ -467,10 +98,10 @@ * @param {Array} end * @returns {Number} scale */ - getScale : function getScale( start, end ){ + getScale : function( start, end ){ // need two fingers... return ( 2 <= start.length && 2 <= end.length ) ? - Utils.getDistance( end[ 0 ], end[ 1 ] ) / Utils.getDistance( start[ 0 ], start[ 1 ] ) : + XUI_GestureUtils.getDistance( end[ 0 ], end[ 1 ] ) / XUI_GestureUtils.getDistance( start[ 0 ], start[ 1 ] ) : 1; }, @@ -483,7 +114,7 @@ getRotation : function getRotation( start, end ){ // need two fingers return ( 2 <= start.length && 2 <= end.length ) ? - Utils.getAngle( end[ 1 ], end[ 0 ] ) - Utils.getAngle( start[ 1 ], start[ 0 ] ) : + XUI_GestureUtils.getAngle( end[ 1 ], end[ 0 ] ) - XUI_GestureUtils.getAngle( start[ 1 ], start[ 0 ] ) : 0; }, @@ -493,349 +124,393 @@ * @returns {Boolean} is_vertical */ isVertical : function isVertical( direction ){ - return direction === Hammer.DIRECTION_UP || direction === Hammer.DIRECTION_DOWN; + return direction === 'up' || direction === 'down'; } }; - - /* - * this holds the last move event, - * used to fix empty touchend issue - * see the onTouch event for an explanation - * @type {Object} - */ - var last_move_event = null; - /* - * when the mouse is hold down, this is true - * @type {Boolean} - */ - var enable_detect = false; +var XUI_Gesture_POINTERS = {}, + XUI_Gesture_CAPTURED = {}, + XUI_Gesture_DEFAULTS = {}; - /* - * when touch events have been fired, this is true - * @type {Boolean} - */ - var touch_triggered = false; - - var Detection = { - // contains all registred Gestures in the correct order - gestures : [], +// AbstractUINode に移動 - // data of the current Hammer.gesture detection session - current : null, +var XUI_Gesture = Hammer = X_Class_create( + 'X.UI.Gesture', + X_Class.NONE, + { + uinodeRoot : null, + uinode : null, + options : null, + + activated : null, + types : null, - // the previous Hammer.gesture session data - // is a full clone of the previous gesture.current object - previous : null, + triggered : null, + canceled : null, + + currentName : '', + startEvent : null, + lastEvent : null, + lastMoveEvent : null, + + 'Constructor' : function( uinodeRoot, uinode, type, opt_options ){ + this.uinodeRoot = uinodeRoot; + this.uinode = uinode; + this.options = X_Object_override( X_Object_copy( XUI_Gesture_DEFAULTS ), opt_options ); + + this.triggered = {}; + this.canceled = {}; - // when this becomes true, no gestures are fired - stopped : false, + uinode[ 'listen' ]( XUI_Event._POINTER_DOWN, this, XUI_Gesture_handleEvent ); + + this[ 'listen' ]( type ); + }, + + trigger : function( type, gesture ){ + var e; + + if( !this.types[ type ] ) return X_CALLBACK_NONE; + e = X_Object_copy( gesture ); + e.type = type; + return this.uinode[ 'dispatch' ]( e ) || X_CALLBACK_NONE; + }, + + listen : function( type ){ + var gestures = XUI_Gesture_LIST, + i = gestures.length, g; + + for( ; i; ){ + g = gestures[ --i ]; + if( g.startID <= type && type <= g.endID ){ + if( !this.activated ) this.activated = {}; + if( !this.types ) this.types = {}; + this.activated[ g.name ] = this.types[ type ] = 1; + break; + }; + }; + }, + + unlisten : function( type ){ + var gestures = XUI_Gesture_LIST, + i = gestures.length, + active = this.activated, g; + + if( !active ) return; + for( ; i; ){ + g = gestures[ --i ]; + if( g.startID <= type && type <= g.endID ){ + if( active[ g.name ] ){ + if( this.types[ type ] ) delete this.types[ type ]; + for( i = g.startID; i <= g.endID; ++i ){ + if( this.types[ i ] ) return; + }; + delete active[ g.name ]; + }; + break; + }; + }; + } + } +); + +function XUI_Gesture_handleEvent( e ){ + var gestures = XUI_Gesture_LIST, + type = e.type, + uid = e[ 'pointerId' ], + isStart = type === XUI_Event._POINTER_DOWN, + isEnd = type === XUI_Event._POINTER_UP || type === XUI_Event._POINTER_CANCEL || type === XUI_Event.POINTER_OUT, + hammer = this, + isMouse = e.pointerType === 'mouse', + touches = [], + numTouches = 0,// count the total touches on the screen + i, p, l, j, captured, ret, activated, gesture, startEv, + deltaTime, deltaX, deltaY, velocity, center, startCenter; - /** - * clear the Hammer.gesture vars - * this is called on endDetect, but can also be used when a final Hammer.gesture has been detected - * to stop other Gestures from being fired - */ - stopDetect : function stopDetect() { - // clone current data to the store as the previous gesture - // used for the double tap gesture, since this is an other gesture detect session - Detection.previous = Utils.extend( {}, Detection.current ); + if( !isStart && !hammer.startEvent ) return; - // reset the current - Detection.current = null; +if( type === XUI_Event.POINTER_OUT ) console.log( 'canceled ...' + e.button ) - // stopped! - Detection.stopped = true; - }, + if( isEnd ){ + if( XUI_Gesture_POINTERS[ uid ] ){ + delete XUI_Gesture_POINTERS[ uid ]; + if( XUI_Gesture_CAPTURED[ uid ] ) delete XUI_Gesture_CAPTURED[ uid ]; + }; + } else { + XUI_Gesture_POINTERS[ uid ] = e; + }; - /** - * register new gesture - * @param {Object} gesture object, see gestures.js for documentation - * @returns {Array} gestures - */ - register : function( gesture ){ - // add an enable gesture options if there is no given - var options = gesture.defaults || {}, - list = Detection.gestures, - _index, i = 0, l = list.length, index; - if( options[ gesture.name ] === undefined ) options[ gesture.name ] = true; - - // extend Hammer default options with the Hammer.gesture options - Utils.extend( Hammer.defaults, options, true ); - - // set its index - gesture.index = gesture.index || 1000; - - // add Hammer.gesture to the list - //Detection.gestures.push( gesture ); - - // sort the list by index - //Detection.gestures.sort( function( a, b ){ - // return - // a.index < b.index ? -1 : - // a.index > b.index ? 1 : 0; - //}); - if( l === 0 ){ - list[ 0 ] = gesture; - return; + // mousebutton must be down or a touch event + if( ( isEnd || !isMouse || e.button === 0 ) ){ + numTouches = -1; + + for( i in XUI_Gesture_POINTERS ){ + if( p = XUI_Gesture_POINTERS[ i ] ){ + // いずれかの hammer によって束縛されている場合、その束縛している hammer なら + captured = XUI_Gesture_CAPTURED[ p[ 'pointerId' ] ]; + if( captured && captured !== hammer ){ + continue; + }; + touches[ ++numTouches ] = p; + }; }; - _index = gesture.index; - for( i = 0; i < l; ++i ){ - index = list[ i ].index; - if( i === 0 && _index < index ){ - list.unshift( gesture ); - return; - } else - if( i === l - 1 ){ - list[ l ] = gesture; - return; - } else - if( index <= _index && _index < list[ i + 1 ].index ){ - list.splice( i, 0, gesture ); - return; + ++numTouches; + + // if we are in a end event, but when we remove one touch and + // we still have enough, set eventType to move + if( !numTouches ){ // no touches, force the end event + isEnd = true; + }; + + // because touchend has no touches, and we often want to use these in our gestures, + // we send the last move event as our eventData in touchend + ( isEnd && hammer.lastMoveEvent ) ? ( e = hammer.lastMoveEvent ) : ( hammer.lastMoveEvent = e ); // store the last move event + + hammerEvent = X_Object_copy( e ); + hammerEvent.touches = touches; + + if( isStart && !hammer.startEvent ){ + console.log( '=- add -=' ); + // already busy with a Hammer.gesture detection on an element + hammer.startEvent = hammerEvent; + hammer.uinodeRoot[ 'listen' ]( [ XUI_Event._POINTER_MOVE, XUI_Event._POINTER_UP, XUI_Event._POINTER_CANCEL, XUI_Event.POINTER_OUT ], hammer, XUI_Gesture_handleEvent ); + }; + + startEv = hammer.startEvent; + + + // if the touches change, set the new touches over the startEvent touches + // this because touchevents don't have all the touches on touchstart, or the + // user must place his fingers at the EXACT same time on the screen, which is not realistic + // but, sometimes it happens that both fingers are touching at the EXACT same time + if( startEv && ( numTouches !== startEv.touches.length || touches !== startEv.touches ) ){ + // extend 1 level deep to get the touchlist with the touch objects + startEv.touches.length = i = 0; + j = -1; + for( ; i < numTouches; ++i ){ + startEv.touches[ ++j ] = touches[ i ]; }; }; - } - }; - var Gestures = Gestures || {}; + deltaTime = hammerEvent.timestamp - startEv.timestamp; + center = XUI_GestureUtils.getCenter( touches ); + startCenter = startEv.center; + deltaX = startCenter ? ( center.pageX - startCenter.pageX ) : 0; + deltaY = startCenter ? ( center.pageY - startCenter.pageY ) : 0; + velocity = XUI_GestureUtils.getVelocity( deltaTime, deltaX, deltaY ); - /** - * Custom gestures - * ============================== - * - * Gesture object - * -------------------- - * The object structure of a gesture: - * - * { name: 'mygesture', - * index: 1337, - * defaults: { - * mygesture_option: true - * } - * handler: function(type, e, inst) { - * // trigger gesture event - * inst.trigger(this.name, e ); - * } - * } - - * @param {String} name - * this should be the name of the gesture, lowercase - * it is also being used to disable/enable the gesture per instance config. - * - * @param {Number} [index=1000] - * the index of the gesture, where it is going to be in the stack of gestures detection - * like when you build an gesture that depends on the drag gesture, it is a good - * idea to place it after the index of the drag gesture. - * - * @param {Object} [defaults={}] - * the default settings of the gesture. these are added to the instance settings, - * and can be overruled per instance. you can also add the name of the gesture, - * but this is also added by default (and set to true). - * - * @param {Function} handler - * this handles the gesture detection of your custom gesture and receives the - * following arguments: - * - * @param {Object} eventData - * event data containing the following properties: - * timeStamp {Number} time the event occurred - * target {HTMLElement} target element - * touches {Array} touches (fingers, pointers, mouse) on the screen - * pointerType {String} kind of pointer that was used. matches Hammer.POINTER_MOUSE|TOUCH - * center {Object} center position of the touches. contains pageX and pageY - * deltaTime {Number} the total time of the touches in the screen - * deltaX {Number} the delta on x axis we haved moved - * deltaY {Number} the delta on y axis we haved moved - * velocityX {Number} the velocity on the x - * velocityY {Number} the velocity on y - * angle {Number} the angle we are moving - * direction {String} the direction we are moving. matches Hammer.DIRECTION_UP|DOWN|LEFT|RIGHT - * distance {Number} the distance we haved moved - * scale {Number} scaling of the touches, needs 2 touches - * rotation {Number} rotation of the touches, needs 2 touches * - * eventType {String} matches Hammer.EVENT_START|MOVE|END - * srcEvent {Object} the source event, like TouchStart or MouseDown * - * startEvent {Object} contains the same properties as above, - * but from the first touch. this is used to calculate - * distances, deltaTime, scaling etc - * - * @param {Hammer.Instance} inst - * the instance we are doing the detection for. you can get the options from - * the inst.options object and trigger the gesture event by calling inst.trigger - * - * - * Handle gestures - * -------------------- - * inside the handler you can get/set Detection.current. This is the current - * detection session. It has the following properties - * @param {String} name - * contains the name of the gesture we have detected. it has not a real function, - * only to check in other gestures if something is detected. - * like in the drag gesture we set it to 'drag' and in the swipe gesture we can - * check if the current gesture is 'drag' by accessing Detection.current.name - * - * @readonly - * @param {Hammer.Instance} inst - * the instance we do the detection for - * - * @readonly - * @param {Object} startEvent - * contains the properties of the first gesture detection in this session. - * Used for calculations about timing, distance, etc. - * - * @readonly - * @param {Object} lastEvent - * contains all the properties of the last gesture detect in this session. - * - * after the gesture detection session has been completed (user has released the screen) - * the Detection.current object is copied into Detection.previous, - * this is usefull for gestures like doubletap, where you need to know if the - * previous gesture was a tap - * - * options that have been set by the instance can be received by calling inst.options - * - * You can trigger a gesture event by calling inst.trigger("mygesture", event). - * The first param is the name of your gesture, the second the event argument - * - * - * Register gestures - * -------------------- - * When an gesture is added to the Gestures object, it is auto registered - * at the setup of the first Hammer instance. You can also call Detection.register - * manually and pass your gesture object as a param - * - */ + X_Object_override( hammerEvent, { + type : isEnd ? XUI_Event._POINTER_UP : type, + + deltaTime : deltaTime, - /** - * Hold - * Touch stays at the same place for x time - * @events hold holdend - */ - Gestures.Hold = { - name : 'hold', - index : 10, - startID : XUI_Event.HOLD, - endID : XUI_Event.HOLD_END, - defaults : { - hold_timeout : 500, - hold_threshold : 1 - }, - timerID : null, - holding : false, - handler : function holdGesture( e, hammer ){ - switch( e.eventType ){ - case START : - // clear any running timers - this.timerID && X_Timer_remove( this.timerID ); - - // set the gesture so we can check in the timeout if it still is - Detection.current.name = this.name; - Gestures.Hold.holding = false; - - // set timer and if after the timeout it still is hold, - // we trigger the hold event - this.timerID = X_Timer_add( hammer.options.hold_timeout, 1, Gestures.Hold._onTimer, [ e, hammer ] ); - return; - - // when you move or end we clear the timer - case MOVE : - if( e.distance <= hammer.options.hold_threshold ) return; - case END : - this.timerID && X_Timer_remove( this.timerID ); - if( Gestures.Hold.holding === true ){ - Gestures.Hold.holding = false; - return hammer.trigger( XUI_Event.HOLD_END, e ); + deltaX : deltaX, + deltaY : deltaY, + + velocityX : velocity.x, + velocityY : velocity.y, + + center : center, + distance : startCenter ? XUI_GestureUtils.getDistance( startCenter, center ) : 0, + angle : startCenter ? XUI_GestureUtils.getAngle( startCenter, center ) : 0, + direction : startCenter ? XUI_GestureUtils.getDirection( startCenter, center ) : 0, + + scale : XUI_GestureUtils.getScale( startEv.touches, touches ), + rotation : XUI_GestureUtils.getRotation( startEv.touches, touches ), + + startEvent : startEv + }); + + // store as previous event event + hammer.lastEvent = hammerEvent; + activated = hammer.activated; + + // call Hammer.gesture handlers + for( i = 0, l = gestures.length; i < l; ++i ){ + gesture = gestures[ i ]; + + if( activated[ gesture.name ] && !hammer.canceled[ gesture.name ] ){ + ( console.log( '... ' + i + ' ' + gesture.name ) ); + // if a handler returns false, we stop with the detection + ( ret |= ( gesture.handler( hammerEvent, hammer ) || X_CALLBACK_NONE ) ); + }; + + if( ret & X_CALLBACK_CAPTURE_POINTER ){ + for( i = touches.length; i; ){ + uid = touches[ --i ][ 'pointerId' ]; + XUI_Gesture_CAPTURED[ uid ] = hammer; + //console.log( 'captured. ' + uid ); }; break; + } else + if( ret & X_CALLBACK_STOP_NOW ){ + break; + }; }; - }, - _onTimer : function( e, hammer ){ - if( Detection.current.name === 'hold' ){ - hammer.trigger( XUI_Event.HOLD, e ); - Gestures.Hold.holding = true; + //console.log( '----' ); + } else { + + }; + + if( isEnd || ( ret & X_CALLBACK_RELEASE_POINTER ) ){ + for( i = touches.length; i; ){ + uid = touches[ --i ][ 'pointerId' ]; + if( XUI_Gesture_CAPTURED[ uid ] === hammer ){ + console.log( 'released. ' + uid ); + delete XUI_Gesture_CAPTURED[ uid ]; + }; }; - } - }; + }; + + if( isEnd ){ + console.log( '=- clear -=' ); + hammer.uinodeRoot[ 'unlisten' ]( [ XUI_Event._POINTER_MOVE, XUI_Event._POINTER_UP, XUI_Event._POINTER_CANCEL, XUI_Event.POINTER_OUT ], hammer, XUI_Gesture_handleEvent ); + + hammer.previous = { + currentName : hammer.currentName, + startEvent : hammer.startEvent, + lastEvent : hammer.lastEvent, + lastMoveEvent : hammer.lastMoveEvent + }; + + X_Object_clear( hammer.triggered ); + X_Object_clear( hammer.canceled ); + + delete hammer.currentName; + delete hammer.startEvent; + delete hammer.lastEvent; + delete hammer.lastMoveEvent; + + ret |= X_CALLBACK_RELEASE_POINTER; + }; + + return ret; +}; + + +var XUI_Gesture_LIST = [ /** - * Tap/DoubleTap - * Quick touch at a place or double at the same place - * @events tap, doubletap + * Touch + * Called as first, tells the user has touched the screen + * @events touch */ - Gestures.Tap = { - name : 'tap', - index : 100, - startID : XUI_Event.TAP, - endID : XUI_Event.DOUBLE_TAP, + { + name : 'touch', + index : -Infinity, defaults : { - tap_max_touchtime : 250, - tap_max_distance : 10, - tap_always : true, - doubletap_distance : 20, - doubletap_interval : 300 - }, - handler : function tapGesture( e, hammer ){ - // previous gesture, for the double tap since these are two different gesture detections - var prev = Detection.previous; - if( e.eventType === END ){ - // when the touchtime is higher then the max touch time - // or when the moving distance is too much - if( hammer.options.tap_max_touchtime < e.deltaTime || hammer.options.tap_max_distance < e.distance ) return; + // call preventDefault at touchstart, and makes the element blocking by + // disabling the scrolling of the page, but it improves gestures like + // transforming and dragging. + // be careful with using this, it can be very annoying for users to be stuck + // on the page + prevent_default : false, - // check if double tap - if( prev && prev.name === 'tap' && ( e.timeStamp - prev.lastEvent.timeStamp ) < hammer.options.doubletap_interval && e.distance < hammer.options.doubletap_distance ){ - return hammer.trigger( XUI_Event.DOUBLE_TAP, e ); - } else - // do a single tap - if( hammer.options.tap_always && Detection.current.name !== 'tap' ){ // EventFire中にalert すると mouseleave で再び呼ばれるのを防ぐ - Detection.current.name = 'tap'; - return hammer.trigger( XUI_Event.TAP, e ); - }; + // disable mouse events, so only touch (or pen!) input triggers events + prevent_mouseevents : false + }, + handler : function( e, hammer ){ + if( hammer.options.prevent_mouseevents && e[ 'pointerType' ] === 'mouse' ){ + return X_CALLBACK_STOP_NOW; }; - } - }; + //hammer.options.prevent_default && e.preventDefault(); + + return e.type === XUI_Event._POINTER_DOWN && hammer.trigger( XUI_Event.TOUCH, e ); + } + }, + /** - * Swipe - * triggers swipe events when the end velocity is above the threshold - * @events swipe, swipeleft, swiperight, swipeup, swipedown + * Transform + * User want to scale or rotate with 2 fingers + * @events transform, transformstart, transformend, pinch, pinchin, pinchout, rotate */ - Gestures.Swipe = { - name : 'swipe', - index : 40, - startID : XUI_Event.SWIP, - endID : XUI_Event.SWIP_DOWN, + { + name : 'transform', + index : 45, + startID : XUI_Event.TRANSFORM, + endID : XUI_Event.ROTATE, defaults : { - // set 0 for unlimited, but this can conflict with transform - swipe_max_touches : 1, - swipe_velocity : 0.7 + // factor, no scale is 1, zoomin is to 0 and zoomout until higher then 1 + transform_min_scale : 0.01, + // rotation in degrees + transform_min_rotation : 1, + // prevent default browser behavior when two touches are on the screen + // but it makes the element a blocking element + // when you are using the transform gesture, it is a good practice to set this true + transform_always_block : false }, - handler : function swipeGesture(e, hammer) { - if( e.eventType === END ){ - // max touches - if( 0 < hammer.options.swipe_max_touches && hammer.options.swipe_max_touches < e.touches.length ) return; - - // when the distance we moved is too small we skip this gesture - // or we can be already in dragging - if( hammer.options.swipe_velocity < e.velocityX || hammer.options.swipe_velocity < e.velocityY ){ - // trigger swipe events - hammer.trigger( XUI_Event.SWIP, e ); - hammer.trigger( - e.direction === Hammer.DIRECTION_UP ? - XUI_Event.SWIP_UP : - e.direction === Hammer.DIRECTION_DOWN ? - XUI_Event.SWIP_DOWN : - e.direction === Hammer.DIRECTION_LEFT ? - XUI_Event.SWIP_LEFT : - XUI_Event.SWIP_RIGHT, - e - ); - }; + + handler : function( e, hammer ){ + var transform = this, ret = X_CALLBACK_NONE, scale_threshold, rotation_threshold; + + // current gesture isnt drag, but dragged is true + // this means an other gesture is busy. now call dragend + if( hammer.currentName !== transform.name && hammer.triggered[ transform.name ] ){ + ret = hammer.trigger( XUI_Event.TRANSFORM_END, e ); + delete hammer.triggered[ transform.name ]; + return ret; }; - } - }; + // atleast multitouch + if( e.touches.length < 2 ) return; + + // prevent default when two fingers are on the screen + //hammer.options.transform_always_block && e.preventDefault(); + + switch( e.type ){ + case XUI_Event._POINTER_DOWN : + //hammer.triggered[ transform.name ] = false; + break; + + case XUI_Event._POINTER_MOVE: + scale_threshold = Math.abs( 1 - e.scale ); + rotation_threshold = Math.abs( e.rotation ); + + // when the distance we moved is too small we skip this gesture + // or we can be already in dragging + if( scale_threshold < hammer.options.transform_min_scale && rotation_threshold < hammer.options.transform_min_rotation ) return; + + // we are transforming! + hammer.currentName = transform.name; + + // first time, trigger dragstart event + if( !hammer.triggered[ transform.name ] ){ + ret = hammer.trigger( XUI_Event.TRANSFORM_START, e ); + if( ret & X_CALLBACK_PREVENT_DEFAULT ){ + hammer.canceled[ transform.name ] = true; + break; + }; + hammer.triggered[ transform.name ] = true; + break; + }; + + ret |= hammer.trigger( XUI_Event.TRANSFORM, e ); + // basic transform event + + // trigger rotate event + if( hammer.options.transform_min_rotation < rotation_threshold ){ + ret |= hammer.trigger( XUI_Event.ROTATE, e ); + }; + + // trigger pinch event + if( scale_threshold > hammer.options.transform_min_scale ){ + ret |= hammer.trigger( XUI_Event.PINCH, e ); + ret |= hammer.trigger( e.scale < 1 ? XUI_Event.PINCH_IN : XUI_Event.PINCH_OUT, e ); + }; + break; + + case XUI_Event.POINTER_OUT : + case XUI_Event._POINTER_CANCEL : + case XUI_Event._POINTER_UP : + // trigger dragend + ret = hammer.triggered[ transform.name ] && hammer.trigger( XUI_Event.TRANSFORM_END, e ); + hammer.triggered[ transform.name ] = false; + break; + }; + return ret; + } + }, + /** * Drag * Move with x fingers (default 1) around on the page. Blocking the scrolling when @@ -843,11 +518,12 @@ * you disable scrolling on that area. * @events drag, dragstart, dragend, drapleft, dragright, dragup, dragdown */ - Gestures.Drag = { + { name : 'drag', index : 50, startID : XUI_Event.DRAG, endID : XUI_Event.DRAG_DOWN, + defaults : { drag_min_distance : 10, // set 0 for unlimited, but this can conflict with transform @@ -864,202 +540,150 @@ // This way, locking occurs only when the distance has become large enough to reliably determine the direction drag_lock_min_distance : 25 }, - triggered : false, - handler : function dragGesture( e, hammer ){ - var last_direction; + + handler : function( e, hammer ){ + var drag = this, last_direction, ret; + // current gesture isnt drag, but dragged is true // this means an other gesture is busy. now call dragend - if( Detection.current.name !== this.name && this.triggered ){ - hammer.trigger( XUI_Event.DRAG_END, e ); - this.triggered = false; - return; + if( hammer.currentName !== drag.name && hammer.triggered[ drag.name ] ){ + ret = hammer.trigger( XUI_Event.DRAG_END, e ); + hammer.triggered[ drag.name ] = false; + return ret; }; // max touches if( 0 < hammer.options.drag_max_touches && hammer.options.drag_max_touches < e.touches.length ) return; - - switch( e.eventType ){ - case START: - this.triggered = false; + + switch( e.type ){ + case XUI_Event._POINTER_DOWN : + hammer.triggered[ drag.name ] = false; break; - case MOVE : + case XUI_Event._POINTER_MOVE : // when the distance we moved is too small we skip this gesture // or we can be already in dragging - if( e.distance < hammer.options.drag_min_distance && Detection.current.name !== this.name ) return; + if( e.distance < hammer.options.drag_min_distance && hammer.currentName !== drag.name ) return; // we are dragging! - Detection.current.name = this.name; + hammer.currentName = drag.name; // lock drag to axis? - if( Detection.current.lastEvent.drag_locked_to_axis || ( hammer.options.drag_lock_to_axis && hammer.options.drag_lock_min_distance <= e.distance ) ){ + if( hammer.lastEvent.drag_locked_to_axis || ( hammer.options.drag_lock_to_axis && hammer.options.drag_lock_min_distance <= e.distance ) ){ e.drag_locked_to_axis = true; }; - last_direction = Detection.current.lastEvent.direction; + last_direction = hammer.lastEvent.direction; if( e.drag_locked_to_axis && last_direction !== e.direction ){ // keep direction on the axis that the drag gesture started on - e.direction = Utils.isVertical( last_direction ) ? - ( e.deltaY < 0 ? Hammer.DIRECTION_UP : Hammer.DIRECTION_DOWN ) : - ( e.deltaX < 0 ? Hammer.DIRECTION_LEFT : Hammer.DIRECTION_RIGHT ); + e.direction = XUI_GestureUtils.isVertical( last_direction ) ? + ( e.deltaY < 0 ? 'up' : 'down' ) : + ( e.deltaX < 0 ? 'left' : 'right' ); }; + ret = X_CALLBACK_NONE; + // first time, trigger dragstart event - if( !this.triggered ){ - hammer.trigger( XUI_Event.DRAG_START, e ); - this.triggered = true; + if( !hammer.triggered[ drag.name ] ){ + ret = hammer.trigger( XUI_Event.DRAG_START, e ); + //if( ret & X_CALLBACK_PREVENT_DEFAULT ){ + // hammer.canceled[ drag.name ] = true; + // break; + //}; + ret |= X_CALLBACK_CAPTURE_POINTER; + console.log( '----- drag start ....' + e.type ); + hammer.triggered[ drag.name ] = true; + break; }; + //console.log( '----- drag ....' + e.type ); // trigger normal event - hammer.trigger( XUI_Event.DRAG, e ); + ret = hammer.trigger( XUI_Event.DRAG, e ) | X_CALLBACK_CAPTURE_POINTER; // direction event, like dragdown - hammer.trigger( - e.direction === Hammer.DIRECTION_UP ? + ret |= hammer.trigger( + e.direction === 'up' ? XUI_Event.DRAG_UP : - e.direction === Hammer.DIRECTION_DOWN ? + e.direction === 'down' ? XUI_Event.DRAG_DOWN : - e.direction === Hammer.DIRECTION_LEFT ? + e.direction === 'left' ? XUI_Event.DRAG_LEFT : XUI_Event.DRAG_RIGHT, e ); // block the browser events - ( - ( hammer.options.drag_block_vertical && Utils.isVertical( e.direction ) ) || - ( hammer.options.drag_block_horizontal && !Utils.isVertical( e.direction ) ) - ) && e.preventDefault(); + /* ( + ( hammer.options.drag_block_vertical && XUI_GestureUtils.isVertical( e.direction ) ) || + ( hammer.options.drag_block_horizontal && !XUI_GestureUtils.isVertical( e.direction ) ) + ) && e.preventDefault(); */ break; - case END: + case XUI_Event.POINTER_OUT : + console.log( 'cancel!!' ); + case XUI_Event._POINTER_CANCEL : + case XUI_Event._POINTER_UP: // trigger dragend - this.triggered && hammer.trigger( XUI_Event.DRAG_END, e ); - this.triggered = false; - break; - } - } - }; - - /** - * Transform - * User want to scale or rotate with 2 fingers - * @events transform, transformstart, transformend, pinch, pinchin, pinchout, rotate - */ - Gestures.Transform = { - name : 'transform', - index : 45, - startID : XUI_Event.TRANSFORM, - endID : XUI_Event.ROTATE, - defaults : { - // factor, no scale is 1, zoomin is to 0 and zoomout until higher then 1 - transform_min_scale : 0.01, - // rotation in degrees - transform_min_rotation : 1, - // prevent default browser behavior when two touches are on the screen - // but it makes the element a blocking element - // when you are using the transform gesture, it is a good practice to set this true - transform_always_block : false - }, - triggered : false, - handler : function transformGesture( e, hammer ){ - // current gesture isnt drag, but dragged is true - // this means an other gesture is busy. now call dragend - if( Detection.current.name !== this.name && this.triggered ){ - hammer.trigger( XUI_Event.TRANSFORM_END, e ); - this.triggered = false; - return; - }; - - // atleast multitouch - if( e.touches.length < 2 ) return; - - // prevent default when two fingers are on the screen - hammer.options.transform_always_block && e.preventDefault(); - - switch(e.eventType) { - case START: - this.triggered = false; - break; - - case MOVE: - var scale_threshold = ABS( 1 - e.scale ), - rotation_threshold = ABS( e.rotation ); - - // when the distance we moved is too small we skip this gesture - // or we can be already in dragging - if( scale_threshold < hammer.options.transform_min_scale && rotation_threshold < hammer.options.transform_min_rotation ) return; - - // we are transforming! - Detection.current.name = this.name; - - // first time, trigger dragstart event - if( !this.triggered ){ - hammer.trigger( XUI_Event.TRANSFORM_START, e ); - this.triggered = true; + if( hammer.triggered[ drag.name ] ){ + ret = hammer.trigger( XUI_Event.DRAG_END, e ) | X_CALLBACK_CAPTURE_POINTER; + console.log( '----- drag end ....' + e.type ); + hammer.triggered[ drag.name ] = false; }; - - hammer.trigger( XUI_Event.TRANSFORM, e ); - // basic transform event - - // trigger rotate event - hammer.options.transform_min_rotation < rotation_threshold && hammer.trigger( XUI_Event.ROTATE, e ); - - // trigger pinch event - if( scale_threshold > hammer.options.transform_min_scale ){ - hammer.trigger( XUI_Event.PINCH, e ); - hammer.trigger( e.scale < 1 ? XUI_Event.PINCH_IN : XUI_Event.PINCH_OUT, e ); - }; - break; - - case END: - // trigger dragend - this.triggered && hammer.trigger( XUI_Event.TRANSFORM_END, e ); - this.triggered = false; break; }; + return ret; } - }; + }, /** - * Touch - * Called as first, tells the user has touched the screen - * @events touch + * Tap/DoubleTap + * Quick touch at a place or double at the same place + * @events tap, doubletap */ - Gestures.Touch = { - name : 'touch', - index : -Infinity, + { + name : 'tap', + index : 100, + startID : XUI_Event.TAP, + endID : XUI_Event.DOUBLE_TAP, defaults : { - // call preventDefault at touchstart, and makes the element blocking by - // disabling the scrolling of the page, but it improves gestures like - // transforming and dragging. - // be careful with using this, it can be very annoying for users to be stuck - // on the page - prevent_default : false, - - // disable mouse events, so only touch (or pen!) input triggers events - prevent_mouseevents : false + tap_min_touchtime : 75, + tap_max_touchtime : 250, + tap_max_distance : 3, + tap_always : true, + doubletap_distance : 20, + doubletap_interval : 300 }, - handler : function touchGesture( e, hammer ){ - if( hammer.options.prevent_mouseevents && e.pointerType === MOUSE ){ - Detection.stopDetect(); - return; + handler : function( e, hammer ){ + // previous gesture, for the double tap since these are two different gesture detections + var prev = hammer.previous; + + if( e.type === XUI_Event._POINTER_UP ){ + // when the touchtime is higher then the max touch time + // or when the moving distance is too much + if( hammer.options.tap_max_touchtime < e.deltaTime || hammer.options.tap_max_distance < e.distance ) return; +//console.log( ' rap? ' + e.deltaTime + 'ms' ); + //if( e.deltaTime < hammer.options.tap_min_touchtime ) return; + + // check if double tap + if( prev && prev.currentName === 'tap' && ( e.timestamp - prev.lastEvent.timestamp ) < hammer.options.doubletap_interval && e.distance < hammer.options.doubletap_distance ){ + return hammer.trigger( XUI_Event.DOUBLE_TAP, e ); + } else + // do a single tap + if( hammer.options.tap_always && hammer.currentName !== 'tap' ){ // EventFire中にalert すると mouseleave で再び呼ばれるのを防ぐ + //hammer.currentName = 'tap'; + console.log( 'tap! ' + e.deltaTime + 'ms' ); + return hammer.trigger( XUI_Event.TAP, e ); + }; }; + } + } - hammer.options.prevent_default && e.preventDefault(); +]; - e.eventType === START && hammer.trigger( this.name, e ); - } +(function( i, g ){ + for( ; i; ){ + g = XUI_Gesture_LIST[ --i ]; + X_Object_override( XUI_Gesture_DEFAULTS, g.defaults ); + delete g.defaults; }; +})( XUI_Gesture_LIST.length ); - /** - * Release - * Called as last, tells the user has released the screen - * @events release - */ - Gestures.Release = { - name : 'release', - index : Infinity, - handler : function releaseGesture( e, hammer ){ - e.eventType === END && hammer.trigger( this.name, e ); - } - };